Skip to content

Commit 1679216

Browse files
committed
moved CI to GH actions, took phpstan to lvl 9
1 parent 466ff32 commit 1679216

15 files changed

Lines changed: 299 additions & 98 deletions

.devcontainer/devcontainer.json

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
22
// README at: https://github.com/devcontainers/templates/tree/main/src/php
33
{
4-
"name": "PHP",
4+
"name": "PHP 8.2",
55
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
66
"image": "mcr.microsoft.com/devcontainers/php:1-8.2-bullseye",
77

@@ -10,21 +10,31 @@
1010
// Configure properties specific to VS Code.
1111
"vscode": {
1212
"extensions": [
13-
"ikappas.composer"
13+
"ikappas.composer",
14+
"neilbrayfield.php-docblocker",
15+
"mehedidracula.php-namespace-resolver",
16+
"github.vscode-github-actions",
17+
"-xdebug.php-debug",
18+
"nhoizey.gremlins",
19+
"oderwat.indent-rainbow",
20+
"bmewburn.vscode-intelephense-client",
21+
"pflannery.vscode-versionlens",
22+
"sonarsource.sonarlint-vscode",
23+
"editorconfig.editorconfig",
24+
"predrag-nikolic.php-class-helper",
25+
"redhat.vscode-yaml"
1426
]
1527
}
1628
},
1729

1830
// Use 'forwardPorts' to make a list of ports inside the container available locally.
19-
"forwardPorts": [
20-
8080
21-
],
31+
// "forwardPorts": [],
2232
"features": {
2333
"ghcr.io/devcontainers/features/github-cli:1": {}
2434
},
2535

2636
// Use 'postCreateCommand' to run commands after the container is created.
27-
"postCreateCommand": "sudo chmod a+x \"$(pwd)\" && sudo rm -rf /var/www/html && sudo ln -s \"$(pwd)\" /var/www/html; if [ -f composer.json ];then composer install;fi"
37+
"postCreateCommand": "if [ -f composer.json ];then composer install;fi"
2838

2939
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
3040
// "remoteUser": "root"

.github/workflows/codacy.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# This workflow uses actions that are not certified by GitHub.
2+
# They are provided by a third-party and are governed by
3+
# separate terms of service, privacy policy, and support
4+
# documentation.
5+
6+
# This workflow checks out code, performs a Codacy security scan
7+
# and integrates the results with the
8+
# GitHub Advanced Security code scanning feature. For more information on
9+
# the Codacy security scan action usage and parameters, see
10+
# https://github.com/codacy/codacy-analysis-cli-action.
11+
# For more information on Codacy Analysis CLI in general, see
12+
# https://github.com/codacy/codacy-analysis-cli.
13+
14+
name: Codacy Security Scan
15+
16+
on:
17+
push:
18+
branches: [ "master" ]
19+
pull_request:
20+
# The branches below must be a subset of the branches above
21+
branches: [ "master" ]
22+
23+
permissions:
24+
contents: read
25+
26+
jobs:
27+
codacy-security-scan:
28+
permissions:
29+
contents: read # for actions/checkout to fetch code
30+
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
31+
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
32+
name: Codacy Security Scan
33+
runs-on: ubuntu-latest
34+
steps:
35+
# Checkout the repository to the GitHub Actions runner
36+
- name: Checkout code
37+
uses: actions/checkout@v4
38+
39+
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
40+
- name: Run Codacy Analysis CLI
41+
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
42+
with:
43+
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
44+
# You can also omit the token and run the tools that support default configurations
45+
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
46+
verbose: true
47+
output: results.sarif
48+
format: sarif
49+
# Adjust severity of non-security issues
50+
gh-code-scanning-compat: true
51+
# Force 0 exit code to allow SARIF file generation
52+
# This will handover control about PR rejection to the GitHub side
53+
max-allowed-issues: 2147483647
54+
55+
# Upload the SARIF file generated in the previous step
56+
- name: Upload SARIF results file
57+
uses: github/codeql-action/upload-sarif@v3
58+
with:
59+
sarif_file: results.sarif

.github/workflows/php.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: PHP Composer
2+
3+
on:
4+
push:
5+
branches: [ "master" ]
6+
pull_request:
7+
branches: [ "master" ]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
build:
14+
name: Composer, test, PHPMD
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: read # for checkout to fetch code
18+
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
19+
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
20+
21+
steps:
22+
- name: 🚚 Get latest code
23+
uses: actions/checkout@v4
24+
25+
- name: Setup PHP
26+
uses: shivammathur/setup-php@v2
27+
with:
28+
coverage: none
29+
extensions: mbstring
30+
tools: phpmd
31+
32+
- name: Setup problem matchers for PHP
33+
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
34+
35+
- name: Update Composer
36+
run: composer self-update
37+
38+
- name: Validate composer.json and composer.lock
39+
run: composer validate --strict
40+
41+
- name: Get composer cache directory
42+
id: composer-cache
43+
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
44+
45+
- name: Cache Composer packages
46+
uses: actions/cache@v4
47+
with:
48+
path: ${{ steps.composer-cache.outputs.dir }}
49+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
50+
restore-keys: ${{ runner.os }}-composer-
51+
52+
- name: Install dependencies
53+
run: composer install --prefer-dist --no-progress
54+
55+
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
56+
# Docs: https://getcomposer.org/doc/articles/scripts.md
57+
58+
- name: Run test suite
59+
run: composer run-script test
60+
61+
- name: Run PHPMD
62+
run: phpmd . sarif codesize --reportfile phpmd-results.sarif
63+
continue-on-error: true
64+
65+
- name: Upload analysis results to GitHub
66+
uses: github/codeql-action/upload-sarif@v3
67+
with:
68+
sarif_file: phpmd-results.sarif
69+
wait-for-processing: true

.github/workflows/psalm.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# This workflow uses actions that are not certified by GitHub.
2+
# They are provided by a third-party and are governed by
3+
# separate terms of service, privacy policy, and support
4+
# documentation.
5+
6+
name: Psalm Security Scan
7+
8+
on:
9+
push:
10+
branches: [ "master" ]
11+
pull_request:
12+
# The branches below must be a subset of the branches above
13+
branches: [ "master" ]
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
php-security:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read # for actions/checkout to fetch code
23+
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
24+
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
25+
26+
steps:
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
30+
- name: Psalm Security Scan
31+
uses: psalm/psalm-github-security-scan@f3e6fd9432bc3e44aec078572677ce9d2ef9c287
32+
33+
- name: Upload Security Analysis results to GitHub
34+
uses: github/codeql-action/upload-sarif@v3
35+
with:
36+
sarif_file: results.sarif

.travis.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,5 @@ The goal of this library is to provide an object interface to interact with stri
1313

1414
- Write tests for Utf8String
1515
- Work on normalization code
16-
- Migrate Travis config to GitHub Action
1716
- Consider using a different testing framework because nobody uses PhpSpec... PHPUnit, Codeception, or Pest
1817
- Flesh out devcontainer config with extensions

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
}
2727
},
2828
"scripts": {
29-
"phpstan": "vendor/bin/phpstan analyse src --level=5"
29+
"phpstan": "vendor/bin/phpstan analyse src --level=9",
30+
"test": "vendor/bin/phpspec run -v"
3031
}
3132
}

src/AbstractString.php

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,16 @@ abstract class AbstractString implements StringObject
99
{
1010
// PROPERTIES
1111

12-
protected $raw;
13-
protected $caret = 0;
14-
protected $token = false;
12+
protected string $raw;
13+
protected int $caret = 0;
14+
protected bool $token = false;
1515

1616
/**
17-
* @param mixed $thing Anything that can be cast to a string
17+
* @param string|object $thing Anything that can be cast to a string
1818
*/
1919
final public function __construct($thing)
2020
{
21-
static::stringableOrFail($thing);
22-
$this->raw = (string) $thing;
21+
$this->raw = static::stringify($thing);
2322
}
2423

2524
public function __get(string $name): mixed
@@ -76,12 +75,12 @@ public function valid(): bool
7675

7776
// END Iterator methods }
7877

78+
/**
79+
* @param string|object $str
80+
*/
7981
public function equals($str): bool
8082
{
81-
static::stringableOrFail($str);
82-
83-
$str = (string) $str;
84-
return ($str == $this->raw);
83+
return (static::stringify($str) == $this->raw);
8584
}
8685

8786
public function length(): int
@@ -111,12 +110,12 @@ public function isEmpty(): bool
111110
return empty($this->raw);
112111
}
113112

114-
public function append($str): static
113+
public function append(string $str): static
115114
{
116115
return new static($this->raw . $str);
117116
}
118117

119-
public function concat($str): static
118+
public function concat(string $str): static
120119
{
121120
return $this->append($str);
122121
}
@@ -139,7 +138,7 @@ public function escape(int $mode = self::NORMAL, string $charlist = ''): static
139138

140139
public function hexDecode(): static
141140
{
142-
return new static(\hex2bin($this->raw));
141+
return new static(\hex2bin($this->raw) ?: '');
143142
}
144143

145144
public function hexEncode(): static
@@ -152,7 +151,7 @@ public function prepend(string $str): static
152151
return new static($str . $this->raw);
153152
}
154153

155-
public function remove(string $str, $mode = self::NORMAL): static
154+
public function remove(string $str, int $mode = self::NORMAL): static
156155
{
157156
return $this->replace($str, '', $mode);
158157
}
@@ -175,6 +174,9 @@ public function replace(string $search, string $replace, int $mode = self::NORMA
175174
return new static(\str_replace($search, $replace, $this->raw));
176175
}
177176

177+
/**
178+
* @param string|string[] $search
179+
*/
178180
public function translate(mixed $search, string $replace = ''): static
179181
{
180182
if (is_array($search)) {
@@ -212,10 +214,10 @@ public function unescape(int $mode = self::NORMAL): static
212214
public function nextToken(string $delim): static
213215
{
214216
if ($this->token) {
215-
return new static(\strtok($delim));
217+
return new static(\strtok($delim) ?: '');
216218
}
217219
$this->token = true;
218-
return new static(\strtok($this->raw, $delim));
220+
return new static(\strtok($this->raw, $delim) ?: '');
219221
}
220222

221223
public function resetToken(): void
@@ -230,21 +232,25 @@ public function times(int $times): static
230232

231233
public function uuDecode(): static
232234
{
233-
return new static(\convert_uudecode($this->raw));
235+
return new static(\convert_uudecode($this->raw) ?: '');
234236
}
235237

236238
public function uuEncode(): static
237239
{
238240
return new static(\convert_uuencode($this->raw));
239241
}
240242

241-
protected static function stringableOrFail($thing): bool
243+
/**
244+
* @param string|object $thing
245+
* @throws InvalidArgumentException
246+
*/
247+
protected static function stringify(mixed $thing): string
242248
{
243-
if (
244-
is_string($thing)
245-
|| (\is_object($thing) && \method_exists($thing, '__toString'))
246-
) {
247-
return true;
249+
if (\is_object($thing) && \method_exists($thing, '__toString')) {
250+
return $thing->__toString();
251+
}
252+
if (\is_string($thing)) {
253+
return $thing;
248254
}
249255

250256
// return false;

0 commit comments

Comments
 (0)