From db4905564b4ad7f859a50e2dab5983387ad54ab9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 14:07:55 +0000 Subject: [PATCH 01/10] Deprecate PHP 7.* support, require PHP 8.0+ This commit removes support for PHP 7.4 and sets the minimum required PHP version to 8.0, enabling the use of modern PHP features and simplifying dependency management. Changes: - Update composer.json to require PHP ^8.0 - Remove symfony/polyfill-php80 dependency (native in PHP 8.0+) - Update Symfony components from ^3.0-8.0 to ^6.0-8.0 - Update phpstan/phpdoc-parser from ^1.2|^2.0 to ^2.0 - Update PHPUnit from ^7.5|^9.0|^10.0 to ^9.6|^10.0|^11.0 - Remove PHP 7.4 from CI test matrix (.github/workflows/build.yml) - Update default Dockerfile PHP version from 7.4 to 8.0 - Remove PHP_7_4 constant from TargetPhpVersion class - Update all tests to use PHP 8.0 as default version - Update README.md to reflect supported PHP versions Benefits: - Enables future use of PHP 8.0+ features (constructor property promotion, match expressions, named arguments, union types, etc.) - Removes support for 3 major Symfony versions (3.x, 4.x, 5.x) - Reduces dependency footprint by removing polyfill - Simplifies testing matrix and maintenance --- .github/workflows/build.yml | 12 +++++------ Dockerfile | 2 +- README.md | 2 +- composer.json | 15 +++++++------- src/CLI/TargetPhpVersion.php | 2 -- .../Analyzer/FileParser/CanParseClassTest.php | 2 +- .../FileParser/CanParseDocblocksTest.php | 20 +++++++++---------- .../CanParseNonWellFormedFilesTest.php | 8 ++++---- tests/Unit/Analyzer/FileParserTest.php | 4 ++-- tests/Unit/CLI/TargetPhpVersionTest.php | 4 ++-- 10 files changed, 34 insertions(+), 37 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4baaa8b5..fda0aef6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] + php-versions: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] coverage-driver: [ 'pcov' ] steps: @@ -43,18 +43,18 @@ jobs: run: composer install --prefer-dist - name: Coding Standard Checks - if: ${{ matrix.php-versions == '7.4' }} + if: ${{ matrix.php-versions == '8.0' }} run: PHP_CS_FIXER_IGNORE_ENV=1 ./bin/php-cs-fixer fix --dry-run --diff - name: Static Analysis - if: ${{ matrix.php-versions == '7.4' }} + if: ${{ matrix.php-versions == '8.0' }} run: ./bin/psalm.phar --no-cache - name: Test run: ./bin/phpunit -d memory_limit=-1 --coverage-clover clover.xml - name: Upload coverage to Codecov - if: ${{ matrix.php-versions == '7.4' }} + if: ${{ matrix.php-versions == '8.0' }} uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -68,7 +68,7 @@ jobs: - name: Install PHP uses: shivammathur/setup-php@v2 with: - php-version: 7.4 + php-version: 8.0 tools: composer:v2.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -97,7 +97,7 @@ jobs: runs-on: "ubuntu-22.04" strategy: matrix: - php-versions: [ '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] + php-versions: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] steps: - name: Install PHP uses: shivammathur/setup-php@v2 diff --git a/Dockerfile b/Dockerfile index 3647b1fe..04a400a3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG PHP_VERSION=7.4 +ARG PHP_VERSION=8.0 FROM php:${PHP_VERSION}-cli-alpine AS php_build diff --git a/README.md b/README.md index 882dc41a..d2d2ce95 100644 --- a/README.md +++ b/README.md @@ -473,7 +473,7 @@ You can add parameters when you launch the tool. At the moment you can add these phparkitect check --config=/project/yourConfigFile.php ``` * `--target-php-version`: With this parameter, you can specify which PHP version should use the parser. This can be useful to debug problems and to understand if there are problems with a different PHP version. -Supported PHP versions are: 7.4, 8.0, 8.1, 8.2 8.3 +Supported PHP versions are: 8.0, 8.1, 8.2, 8.3, 8.4, 8.5 * `--stop-on-failure`: With this option the process will end immediately after the first violation. * `--autoload`: specify the path of an autoload file to be loaded when running phparkitect. diff --git a/composer.json b/composer.json index 74fd10e4..c40a677c 100644 --- a/composer.json +++ b/composer.json @@ -22,15 +22,14 @@ } ], "require": { - "php": "^7.4|^8", + "php": "^8.0", "ext-json": "*", "nikic/php-parser": "~5", "ondram/ci-detector": "^4.2", - "phpstan/phpdoc-parser": "^1.2|^2.0", - "symfony/console": "^3.0|^4.0|^5.0|^6.0|^7.0|^8.0", - "symfony/event-dispatcher": "^3.0|^4.0|^5.0|^6.0|^7.0|^8.0", - "symfony/finder": "^3.0|^4.0|^5.0|^6.0|^7.0|^8.0", - "symfony/polyfill-php80": "^1.33", + "phpstan/phpdoc-parser": "^2.0", + "symfony/console": "^6.0|^7.0|^8.0", + "symfony/event-dispatcher": "^6.0|^7.0|^8.0", + "symfony/finder": "^6.0|^7.0|^8.0", "webmozart/assert": "^1.12" }, "require-dev": { @@ -38,9 +37,9 @@ "mikey179/vfsstream": "^1.6", "phpspec/prophecy": "^1.10", "phpspec/prophecy-phpunit": "^2.4", - "phpunit/phpunit": "^7.5|^9.0|^10.0", + "phpunit/phpunit": "^9.6|^10.0|^11.0", "roave/security-advisories": "dev-master", - "symfony/var-dumper": "^3.0|^4.0|^5.0|^6.0|^7.0|^8.0" + "symfony/var-dumper": "^6.0|^7.0|^8.0" }, "autoload": { "psr-4": { diff --git a/src/CLI/TargetPhpVersion.php b/src/CLI/TargetPhpVersion.php index 64d553fd..1d46d620 100644 --- a/src/CLI/TargetPhpVersion.php +++ b/src/CLI/TargetPhpVersion.php @@ -8,7 +8,6 @@ class TargetPhpVersion { - public const PHP_7_4 = '7.4'; public const PHP_8_0 = '8.0'; public const PHP_8_1 = '8.1'; public const PHP_8_2 = '8.2'; @@ -17,7 +16,6 @@ class TargetPhpVersion public const PHP_8_5 = '8.5'; public const VALID_PHP_VERSIONS = [ - '7.4', '8.0', '8.1', '8.2', diff --git a/tests/Unit/Analyzer/FileParser/CanParseClassTest.php b/tests/Unit/Analyzer/FileParser/CanParseClassTest.php index e7fe8673..86654b39 100644 --- a/tests/Unit/Analyzer/FileParser/CanParseClassTest.php +++ b/tests/Unit/Analyzer/FileParser/CanParseClassTest.php @@ -602,7 +602,7 @@ public function __construct() { private function parseCode(string $code, ?string $version = null): array { - $fp = FileParserFactory::forPhpVersion($version ?? TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion($version ?? TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); return $fp->getClassDescriptions(); diff --git a/tests/Unit/Analyzer/FileParser/CanParseDocblocksTest.php b/tests/Unit/Analyzer/FileParser/CanParseDocblocksTest.php index d0c7c201..c3363c6c 100644 --- a/tests/Unit/Analyzer/FileParser/CanParseDocblocksTest.php +++ b/tests/Unit/Analyzer/FileParser/CanParseDocblocksTest.php @@ -105,7 +105,7 @@ class MyClass } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -134,7 +134,7 @@ class MyClass } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -163,7 +163,7 @@ class MyClass } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -194,7 +194,7 @@ public function __construct(array $dtoList) } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -225,7 +225,7 @@ public function __construct(array $dtoList) } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -256,7 +256,7 @@ public function __construct(array $dtoList) } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -290,7 +290,7 @@ public function __construct(string $var1, array $dtoList, $var2, array $voList) } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -322,7 +322,7 @@ public function getList(): array } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -354,7 +354,7 @@ public function getList(): array } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); @@ -386,7 +386,7 @@ public function getList(): array } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $cd = $fp->getClassDescriptions(); diff --git a/tests/Unit/Analyzer/FileParser/CanParseNonWellFormedFilesTest.php b/tests/Unit/Analyzer/FileParser/CanParseNonWellFormedFilesTest.php index 0650b291..e31adea4 100644 --- a/tests/Unit/Analyzer/FileParser/CanParseNonWellFormedFilesTest.php +++ b/tests/Unit/Analyzer/FileParser/CanParseNonWellFormedFilesTest.php @@ -14,7 +14,7 @@ class CanParseNonWellFormedFilesTest extends TestCase { public function test_should_parse_non_php_file(): void { - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse('', 'path/to/class.php'); self::assertEmpty($fp->getClassDescriptions()); @@ -26,7 +26,7 @@ public function test_should_parse_empty_file(): void parse($code, 'path/to/class.php'); self::assertEmpty($fp->getClassDescriptions()); @@ -48,7 +48,7 @@ public function __construct() } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $parsingErrors = $fp->getParsingErrors(); @@ -78,7 +78,7 @@ public function save(Quote $quote): void; } EOF; - $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_7_4); + $fp = FileParserFactory::forPhpVersion(TargetPhpVersion::PHP_8_0); $fp->parse($code, 'relativePathName'); $violations = new Violations(); diff --git a/tests/Unit/Analyzer/FileParserTest.php b/tests/Unit/Analyzer/FileParserTest.php index a4522c37..951f6a9e 100644 --- a/tests/Unit/Analyzer/FileParserTest.php +++ b/tests/Unit/Analyzer/FileParserTest.php @@ -37,7 +37,7 @@ public function test_parse_file(): void $fileVisitor->reveal(), $nameResolver->reveal(), $docblockResolver->reveal(), - TargetPhpVersion::create('7.4') + TargetPhpVersion::create('8.0') ); $content = 'reveal(), $nameResolver->reveal(), $docblockResolver->reveal(), - TargetPhpVersion::create('7.4') + TargetPhpVersion::create('8.0') ); $content = 'get()); + self::assertEquals('8.0', $targetPhpVersion->get()); } public function test_it_should_throw_exception_if_not_valid_php_version(): void From 2c9dcecbc9a51e6dff94521822ad99ac9a264b8b Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 14:12:09 +0000 Subject: [PATCH 02/10] Fix coding standards: add trailing commas in function signatures PHP-CS-Fixer requires trailing commas in multi-line function parameters for consistency with PHP 8.0+ coding standards. Files updated: - src/Analyzer/ClassDescription.php - src/Analyzer/FileParser.php - src/CLI/Runner.php - src/PHPUnit/ArchRuleCheckerConstraintAdapter.php - src/Rules/ArchRule.php - tests/E2E/Cli/CheckCommandTest.php --- src/Analyzer/ClassDescription.php | 2 +- src/Analyzer/FileParser.php | 2 +- src/CLI/Runner.php | 2 +- src/PHPUnit/ArchRuleCheckerConstraintAdapter.php | 2 +- src/Rules/ArchRule.php | 2 +- tests/E2E/Cli/CheckCommandTest.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Analyzer/ClassDescription.php b/src/Analyzer/ClassDescription.php index 93545a98..6c5e6229 100644 --- a/src/Analyzer/ClassDescription.php +++ b/src/Analyzer/ClassDescription.php @@ -57,7 +57,7 @@ public function __construct( bool $enum, array $docBlock, array $attributes, - string $filePath + string $filePath, ) { $this->FQCN = $FQCN; $this->filePath = $filePath; diff --git a/src/Analyzer/FileParser.php b/src/Analyzer/FileParser.php index e9ea68f0..2d6a6222 100644 --- a/src/Analyzer/FileParser.php +++ b/src/Analyzer/FileParser.php @@ -29,7 +29,7 @@ public function __construct( FileVisitor $fileVisitor, NameResolver $nameResolver, DocblockTypesResolver $docblockTypesResolver, - TargetPhpVersion $targetPhpVersion + TargetPhpVersion $targetPhpVersion, ) { $this->fileVisitor = $fileVisitor; $this->parsingErrors = []; diff --git a/src/CLI/Runner.php b/src/CLI/Runner.php index 6cc9047a..3abe7382 100644 --- a/src/CLI/Runner.php +++ b/src/CLI/Runner.php @@ -44,7 +44,7 @@ public function check( Parser $fileParser, Violations $violations, ParsingErrors $parsingErrors, - bool $stopOnFailure + bool $stopOnFailure, ): void { /** @var SplFileInfo $file */ foreach ($classSetRule->getClassSet() as $file) { diff --git a/src/PHPUnit/ArchRuleCheckerConstraintAdapter.php b/src/PHPUnit/ArchRuleCheckerConstraintAdapter.php index faede6de..5ea448e7 100644 --- a/src/PHPUnit/ArchRuleCheckerConstraintAdapter.php +++ b/src/PHPUnit/ArchRuleCheckerConstraintAdapter.php @@ -61,7 +61,7 @@ public function toString(): string protected function matches( /** @var ArchRule $rule */ - $other + $other, ): bool { $this->runner->check( ClassSetRules::create($this->classSet, $other), diff --git a/src/Rules/ArchRule.php b/src/Rules/ArchRule.php index cd2e772f..8a811ccc 100644 --- a/src/Rules/ArchRule.php +++ b/src/Rules/ArchRule.php @@ -28,7 +28,7 @@ public function __construct( Constraints $constraints, string $because, array $classesToBeExcluded, - bool $runOnlyThis + bool $runOnlyThis, ) { $this->thats = $specs; $this->shoulds = $constraints; diff --git a/tests/E2E/Cli/CheckCommandTest.php b/tests/E2E/Cli/CheckCommandTest.php index 8d6db7e9..c60ef9c5 100644 --- a/tests/E2E/Cli/CheckCommandTest.php +++ b/tests/E2E/Cli/CheckCommandTest.php @@ -269,7 +269,7 @@ protected function runCheck( bool $skipBaseline = false, bool $ignoreBaselineNumbers = false, string $format = 'text', - ?string $autoloadFilePath = null + ?string $autoloadFilePath = null, ): ApplicationTester { $input = ['check']; From 2897ba804d2fed89ec4e8a519c92b0bea5890487 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 14:14:02 +0000 Subject: [PATCH 03/10] Run static analysis on PHP 8.3 instead of 8.0 The current psalm.phar version doesn't support PHP 8.4+. Running static analysis on PHP 8.3 ensures compatibility with the current Psalm binary while still testing against a modern PHP version. This is a temporary solution until psalm.phar is updated to version 7.0+ which supports PHP 8.4 and 8.5. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fda0aef6..eb436643 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: run: PHP_CS_FIXER_IGNORE_ENV=1 ./bin/php-cs-fixer fix --dry-run --diff - name: Static Analysis - if: ${{ matrix.php-versions == '8.0' }} + if: ${{ matrix.php-versions == '8.3' }} run: ./bin/psalm.phar --no-cache - name: Test From 367b1f6a89fe4032bc0d77c903cd3a13a3c411d7 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 16:36:40 +0000 Subject: [PATCH 04/10] Revert static analysis to PHP 8.0 for consistency Run static analysis on PHP 8.0 to maintain consistency with: - Coding standard checks (PHP 8.0) - Code coverage (PHP 8.0) - Phar build (PHP 8.0) The current psalm.phar supports PHP 8.0-8.3, so running on 8.0 works correctly and keeps all quality checks on the same PHP version. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb436643..fda0aef6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,7 +47,7 @@ jobs: run: PHP_CS_FIXER_IGNORE_ENV=1 ./bin/php-cs-fixer fix --dry-run --diff - name: Static Analysis - if: ${{ matrix.php-versions == '8.3' }} + if: ${{ matrix.php-versions == '8.0' }} run: ./bin/psalm.phar --no-cache - name: Test From b7eb503538e65ddda6b573165bd9a6b739b9e2a1 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 16:41:59 +0000 Subject: [PATCH 05/10] Constrain Symfony to versions compatible with PHP 8.0 Symfony 6.4+ requires PHP 8.1, so we constrain Symfony components to: - Symfony 5.4.x (PHP >= 7.2.5) - Symfony 6.0-6.3 (PHP >= 8.0.2) This maintains PHP 8.0 support while avoiding dependency conflicts. Updated constraints: - symfony/console: ^5.4 || ^6.0 <6.4 - symfony/event-dispatcher: ^5.4 || ^6.0 <6.4 - symfony/finder: ^5.4 || ^6.0 <6.4 - symfony/var-dumper: ^5.4 || ^6.0 <6.4 Note: In a future PR, upgrading to PHP 8.1 will unlock Symfony 6.4 LTS (supported until November 2027) and enable modern PHP features like enums and readonly properties. --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index c40a677c..eee3ec63 100644 --- a/composer.json +++ b/composer.json @@ -27,9 +27,9 @@ "nikic/php-parser": "~5", "ondram/ci-detector": "^4.2", "phpstan/phpdoc-parser": "^2.0", - "symfony/console": "^6.0|^7.0|^8.0", - "symfony/event-dispatcher": "^6.0|^7.0|^8.0", - "symfony/finder": "^6.0|^7.0|^8.0", + "symfony/console": "^5.4 || ^6.0 <6.4", + "symfony/event-dispatcher": "^5.4 || ^6.0 <6.4", + "symfony/finder": "^5.4 || ^6.0 <6.4", "webmozart/assert": "^1.12" }, "require-dev": { @@ -39,7 +39,7 @@ "phpspec/prophecy-phpunit": "^2.4", "phpunit/phpunit": "^9.6|^10.0|^11.0", "roave/security-advisories": "dev-master", - "symfony/var-dumper": "^6.0|^7.0|^8.0" + "symfony/var-dumper": "^5.4 || ^6.0 <6.4" }, "autoload": { "psr-4": { From 665e86d3f8b6e1efe8b30ac66d7db0378da58ad8 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 17:05:18 +0000 Subject: [PATCH 06/10] Enable PCOV coverage driver in CI Add coverage driver configuration to setup-php action to enable code coverage collection with PCOV. This fixes the PHPUnit warning: 'No filter is configured, code coverage will not be processed' The coverage driver is configured via matrix strategy (pcov) and now properly passed to setup-php action. --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fda0aef6..d8eb9cae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} + coverage: ${{ matrix.coverage-driver }} tools: composer:v2.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From bd1126a4aa6f37de450821457162970836ff1c02 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 17:07:25 +0000 Subject: [PATCH 07/10] Run coverage only on PHP 8.0, skip on other versions Split test step into two separate steps: - 'Test with coverage' runs only on PHP 8.0 with --coverage-clover - 'Test without coverage' runs on all other versions without coverage This fixes the PHPUnit warning on PHP 8.2+ where PCOV configuration may not be properly set up, and also improves CI performance by only generating coverage once instead of on all 6 PHP versions. Fixes: No filter is configured, code coverage will not be processed --- .github/workflows/build.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d8eb9cae..c7645aba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,9 +51,14 @@ jobs: if: ${{ matrix.php-versions == '8.0' }} run: ./bin/psalm.phar --no-cache - - name: Test + - name: Test with coverage + if: ${{ matrix.php-versions == '8.0' }} run: ./bin/phpunit -d memory_limit=-1 --coverage-clover clover.xml + - name: Test without coverage + if: ${{ matrix.php-versions != '8.0' }} + run: ./bin/phpunit -d memory_limit=-1 + - name: Upload coverage to Codecov if: ${{ matrix.php-versions == '8.0' }} uses: codecov/codecov-action@v5 From 51de2b5cf0ee7be81ab30587dad44d1d23160980 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 14 Dec 2025 20:17:55 +0000 Subject: [PATCH 08/10] Simplify CI: remove redundant coverage-driver matrix The coverage-driver matrix variable had only one value (pcov), making it unnecessary. Simplified by: - Removing coverage-driver from matrix strategy - Hardcoding coverage: pcov in setup-php action This makes the configuration clearer without changing functionality. --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c7645aba..53457df3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,6 @@ jobs: fail-fast: false matrix: php-versions: [ '8.0', '8.1', '8.2', '8.3', '8.4', '8.5' ] - coverage-driver: [ 'pcov' ] steps: - uses: actions/checkout@v5 @@ -23,7 +22,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} - coverage: ${{ matrix.coverage-driver }} + coverage: pcov tools: composer:v2.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4588da40d9ee16bc42c1fd481ca8a34504e354b5 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 20 Dec 2025 12:36:45 +0000 Subject: [PATCH 09/10] Update PHP-CS-Fixer to use PHP 8.0 migration rules Changed from @PHP71Migration:risky to @PHP80Migration:risky to enable PHP 8.0+ coding standards and modernizations. This automatically converts traditional closures to arrow functions where applicable, resulting in cleaner, more concise code. Changes applied: - Updated .php-cs-fixer.dist.php configuration - Converted 7 closures to arrow functions (fn) - Removed outdated PHP 7.3 compatibility comment Benefits: - 20 lines of code removed - More modern PHP 8.0+ syntax - Better alignment with minimum PHP version requirement --- .php-cs-fixer.dist.php | 4 ++-- src/Analyzer/ClassDescription.php | 4 +--- src/Expression/ForClasses/Implement.php | 4 +--- .../ForClasses/NotHaveDependencyOutsideNamespace.php | 4 +--- src/Expression/ForClasses/NotImplement.php | 4 +--- src/RuleBuilders/Architecture/Architecture.php | 8 ++------ src/Rules/Violations.php | 8 ++------ tests/Unit/ClassSetTest.php | 8 ++------ 8 files changed, 12 insertions(+), 32 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 5ea44f9d..f74a4367 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -12,7 +12,7 @@ '@PER-CS' => true, '@Symfony' => true, '@Symfony:risky' => true, - '@PHP71Migration:risky' => true, + '@PHP80Migration:risky' => true, '@PSR2' => true, '@DoctrineAnnotation' => true, 'array_syntax' => ['syntax' => 'short'], @@ -24,7 +24,7 @@ 'modernize_types_casting' => true, // Replaces intval, floatval, doubleval, strval and boolval function calls with according type casting operator. 'multiline_whitespace_before_semicolons' => true, // Forbid multi-line whitespace before the closing semicolon or move the semicolon to the new line for chained calls. 'no_unreachable_default_argument_value' => true, // In function arguments there must not be arguments with default values before non-default ones. - 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], // To avoid problems of compatibility with the old php-cs-fixer version used on PHP 7.3 + 'no_superfluous_phpdoc_tags' => ['allow_mixed' => true], 'no_useless_else' => true, 'no_useless_return' => true, 'ordered_class_elements' => true, // Orders the elements of classes/interfaces/traits. diff --git a/src/Analyzer/ClassDescription.php b/src/Analyzer/ClassDescription.php index 6c5e6229..a0a0d946 100644 --- a/src/Analyzer/ClassDescription.php +++ b/src/Analyzer/ClassDescription.php @@ -196,9 +196,7 @@ public function hasAttribute(string $pattern): bool { return array_reduce( $this->attributes, - static function (bool $carry, FullyQualifiedClassName $attribute) use ($pattern): bool { - return $carry || $attribute->matches($pattern); - }, + static fn (bool $carry, FullyQualifiedClassName $attribute): bool => $carry || $attribute->matches($pattern), false ); } diff --git a/src/Expression/ForClasses/Implement.php b/src/Expression/ForClasses/Implement.php index 6dd906de..a64554de 100644 --- a/src/Expression/ForClasses/Implement.php +++ b/src/Expression/ForClasses/Implement.php @@ -40,9 +40,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str $interface = $this->interface; $interfaces = $theClass->getInterfaces(); - $implements = function (FullyQualifiedClassName $FQCN) use ($interface): bool { - return $FQCN->matches($interface); - }; + $implements = fn (FullyQualifiedClassName $FQCN): bool => $FQCN->matches($interface); if (0 === \count(array_filter($interfaces, $implements))) { $violation = Violation::create( diff --git a/src/Expression/ForClasses/NotHaveDependencyOutsideNamespace.php b/src/Expression/ForClasses/NotHaveDependencyOutsideNamespace.php index 4501d6e1..017ecded 100644 --- a/src/Expression/ForClasses/NotHaveDependencyOutsideNamespace.php +++ b/src/Expression/ForClasses/NotHaveDependencyOutsideNamespace.php @@ -36,9 +36,7 @@ public function describe(ClassDescription $theClass, string $because): Descripti public function evaluate(ClassDescription $theClass, Violations $violations, string $because): void { $namespace = $this->namespace; - $depends = function (ClassDependency $dependency) use ($namespace): bool { - return !$dependency->getFQCN()->matches($namespace); - }; + $depends = fn (ClassDependency $dependency): bool => !$dependency->getFQCN()->matches($namespace); $dependencies = $theClass->getDependencies(); $externalDeps = array_filter($dependencies, $depends); diff --git a/src/Expression/ForClasses/NotImplement.php b/src/Expression/ForClasses/NotImplement.php index 0f410b91..55257f71 100644 --- a/src/Expression/ForClasses/NotImplement.php +++ b/src/Expression/ForClasses/NotImplement.php @@ -40,9 +40,7 @@ public function evaluate(ClassDescription $theClass, Violations $violations, str $interface = $this->interface; $interfaces = $theClass->getInterfaces(); - $implements = function (FullyQualifiedClassName $FQCN) use ($interface): bool { - return $FQCN->matches($interface); - }; + $implements = fn (FullyQualifiedClassName $FQCN): bool => $FQCN->matches($interface); if (\count(array_filter($interfaces, $implements)) > 0) { $violation = Violation::create( diff --git a/src/RuleBuilders/Architecture/Architecture.php b/src/RuleBuilders/Architecture/Architecture.php index 3468830d..18b70512 100644 --- a/src/RuleBuilders/Architecture/Architecture.php +++ b/src/RuleBuilders/Architecture/Architecture.php @@ -90,9 +90,7 @@ public function rules(string $because = 'of component architecture'): iterable $forbiddenComponents = array_diff($layerNames, [$name], $this->allowedDependencies[$name]); if (!empty($forbiddenComponents)) { - $forbiddenSelectors = array_values(array_map(function (string $componentName): string { - return $this->componentSelectors[$componentName]; - }, $forbiddenComponents)); + $forbiddenSelectors = array_values(array_map(fn (string $componentName): string => $this->componentSelectors[$componentName], $forbiddenComponents)); yield Rule::allClasses() ->that(new ResideInOneOfTheseNamespaces($selector)) @@ -105,9 +103,7 @@ public function rules(string $because = 'of component architecture'): iterable continue; } - $allowedDependencies = array_values(array_map(function (string $componentName): string { - return $this->componentSelectors[$componentName]; - }, $this->componentDependsOnlyOnTheseNamespaces[$name])); + $allowedDependencies = array_values(array_map(fn (string $componentName): string => $this->componentSelectors[$componentName], $this->componentDependsOnlyOnTheseNamespaces[$name])); yield Rule::allClasses() ->that(new ResideInOneOfTheseNamespaces($selector)) diff --git a/src/Rules/Violations.php b/src/Rules/Violations.php index 5d17b485..b632870a 100644 --- a/src/Rules/Violations.php +++ b/src/Rules/Violations.php @@ -27,9 +27,7 @@ public static function fromJson(string $json): self $instance = new self(); - $instance->violations = array_map(function (array $json): Violation { - return Violation::fromJson($json); - }, $json['violations']); + $instance->violations = array_map(fn (array $json): Violation => Violation::fromJson($json), $json['violations']); return $instance; } @@ -113,9 +111,7 @@ public function remove(self $violations, bool $ignoreBaselineLinenumbers = false public function sort(): void { - usort($this->violations, static function (Violation $v1, Violation $v2): int { - return $v1 <=> $v2; - }); + usort($this->violations, static fn (Violation $v1, Violation $v2): int => $v1 <=> $v2); } public function jsonSerialize(): array diff --git a/tests/Unit/ClassSetTest.php b/tests/Unit/ClassSetTest.php index c9ba60c0..f810abb5 100644 --- a/tests/Unit/ClassSetTest.php +++ b/tests/Unit/ClassSetTest.php @@ -54,9 +54,7 @@ public function test_can_exclude_files_or_directories(): void 'View/UserView.php', ]; - $actual = array_values(array_map(function ($item) { - return $item->getRelativePathname(); - }, iterator_to_array($set))); + $actual = array_values(array_map(fn ($item) => $item->getRelativePathname(), iterator_to_array($set))); self::assertEquals($expected, $actual); } @@ -83,9 +81,7 @@ public function test_can_exclude_glob_patterns(): void 'View/UserView.php', ]; - $actual = array_values(array_map(function ($item) { - return $item->getRelativePathname(); - }, iterator_to_array($set))); + $actual = array_values(array_map(fn ($item) => $item->getRelativePathname(), iterator_to_array($set))); self::assertEquals($expected, $actual); } From ffff8c2d0bee0f2a7d72289e8350eb2ed4ba1384 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 20 Dec 2025 12:39:17 +0000 Subject: [PATCH 10/10] Update Scrutinizer to use PHP 8.0 Update Scrutinizer CI environment from PHP 7.4 to PHP 8.0 to match the new minimum PHP version requirement. This ensures code quality analysis runs on the correct PHP version. --- .scrutinizer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 7df0ee74..26e02fd5 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -1,4 +1,4 @@ build: environment: - php: 7.4 + php: 8.0