From 0f133419678acd170e0ccb772d667f0806111689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20H=C3=BCbner?= Date: Tue, 27 Jan 2026 20:38:22 +0100 Subject: [PATCH 1/4] Add PHPStan with baseline configuration Add phpstan/phpstan as dev dependency, create phpstan.neon.dist at level 5 with a baseline for existing errors, and add a composer script for running static analysis via `composer run phpstan`. Co-Authored-By: Claude Opus 4.5 --- composer.json | 6 +- phpstan-baseline.neon | 146 ++++++++++++++++++++++++++++++++++++++++++ phpstan.neon.dist | 7 ++ 3 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 phpstan-baseline.neon create mode 100644 phpstan.neon.dist diff --git a/composer.json b/composer.json index d4b1655..2962efb 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "phpunit/phpunit": "^9.5", "rector/rector": "^1.2", "doctrine/orm": "^3.6", - "doctrine/persistence": "^4.1" + "doctrine/persistence": "^4.1", + "phpstan/phpstan": "^1.12" }, "autoload": { "psr-4": { @@ -37,6 +38,7 @@ ], "minimum-stability": "stable", "scripts": { - "tests": "phpunit" + "tests": "phpunit", + "phpstan": "phpstan analyse" } } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..bc4f631 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,146 @@ +parameters: + ignoreErrors: + - + message: "#^Call to method load\\(\\) on an unknown class Symfony\\\\Component\\\\DependencyInjection\\\\Loader\\\\XmlFileLoader\\.$#" + count: 1 + path: src/DependencyInjection/MalteHuebnerDataQueryExtension.php + + - + message: "#^Instantiated class Symfony\\\\Component\\\\DependencyInjection\\\\Loader\\\\XmlFileLoader not found\\.$#" + count: 1 + path: src/DependencyInjection/MalteHuebnerDataQueryExtension.php + + - + message: "#^Deprecated in PHP 8\\.4\\: Parameter \\#3 \\$parameterName \\(string\\) is implicitly nullable via default value null\\.$#" + count: 1 + path: src/Exception/ParameterConverterException.php + + - + message: "#^Call to static method getShortnameFromFqcn\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\ClassUtil\\.$#" + count: 1 + path: src/Factory/ConflictResolver/ConflictResolver.php + + - + message: "#^Variable \\$parameter in PHPDoc tag @var does not match any variable in the foreach loop\\: \\$parameterCandidate$#" + count: 1 + path: src/Factory/ParameterFactory/ParameterFactory.php + + - + message: "#^Variable \\$parameterField in PHPDoc tag @var does not match any variable in the foreach loop\\: \\$fieldName, \\$parameterFields$#" + count: 1 + path: src/Factory/ParameterFactory/ParameterFactory.php + + - + message: "#^Call to static method getShortname\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\ClassUtil\\.$#" + count: 1 + path: src/Factory/QueryFactory/QueryFactory.php + + - + message: "#^Variable \\$entityField in PHPDoc tag @var does not match any variable in the foreach loop\\: \\$entityFields$#" + count: 1 + path: src/Factory/QueryFactory/QueryFactory.php + + - + message: "#^Negated boolean expression is always false\\.$#" + count: 1 + path: src/Factory/ValueAssigner/ValueAssigner.php + + - + message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#" + count: 1 + path: src/FieldList/EntityFieldList/EntityFieldListFactory.php + + - + message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#" + count: 1 + path: src/FieldList/ParameterFieldList/ParameterFieldListFactory.php + + - + message: "#^Call to an undefined method MalteHuebner\\\\DataQueryBundle\\\\FieldList\\\\AbstractField\\:\\:setParameterName\\(\\)\\.$#" + count: 2 + path: src/FieldList/QueryFieldList/QueryFieldListFactory.php + + - + message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#" + count: 2 + path: src/FieldList/QueryFieldList/QueryFieldListFactory.php + + - + message: "#^Call to method find\\(\\) on an unknown class FOS\\\\ElasticaBundle\\\\Repository\\.$#" + count: 1 + path: src/Finder/Finder.php + + - + message: "#^Class MalteHuebner\\\\DataQueryBundle\\\\Finder\\\\AbstractOrmQuery not found\\.$#" + count: 1 + path: src/Finder/Finder.php + + - + message: "#^Parameter \\$repository of method MalteHuebner\\\\DataQueryBundle\\\\Finder\\\\Finder\\:\\:__construct\\(\\) has invalid type FOS\\\\ElasticaBundle\\\\Repository\\.$#" + count: 1 + path: src/Finder/Finder.php + + - + message: "#^Property MalteHuebner\\\\DataQueryBundle\\\\Finder\\\\Finder\\:\\:\\$repository has unknown class FOS\\\\ElasticaBundle\\\\Repository as its type\\.$#" + count: 1 + path: src/Finder/Finder.php + + - + message: "#^Class FOS\\\\ElasticaBundle\\\\Manager\\\\RepositoryManagerInterface not found\\.$#" + count: 2 + path: src/FinderFactory/FinderFactory.php + + - + message: "#^Cannot call method addMust\\(\\) on array\\\\>\\|Elastica\\\\Query\\\\AbstractQuery\\.$#" + count: 1 + path: src/Parameter/StartValueParameter.php + + - + message: "#^Call to static method getDayEndDateTime\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\DateTimeUtil\\.$#" + count: 2 + path: src/Query/DateQuery.php + + - + message: "#^Call to static method getDayStartDateTime\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\DateTimeUtil\\.$#" + count: 2 + path: src/Query/DateQuery.php + + - + message: "#^Call to static method getMonthEndDateTime\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\DateTimeUtil\\.$#" + count: 2 + path: src/Query/MonthQuery.php + + - + message: "#^Call to static method getMonthStartDateTime\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\DateTimeUtil\\.$#" + count: 2 + path: src/Query/MonthQuery.php + + - + message: "#^Call to static method getYearEndDateTime\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\DateTimeUtil\\.$#" + count: 2 + path: src/Query/YearQuery.php + + - + message: "#^Call to static method getYearStartDateTime\\(\\) on an unknown class App\\\\Criticalmass\\\\Util\\\\DateTimeUtil\\.$#" + count: 2 + path: src/Query/YearQuery.php + + - + message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$message\\.$#" + count: 2 + path: src/Validator/BoundingBoxValidator.php + + - + message: "#^PHPDoc tag @var above a method has no effect\\.$#" + count: 1 + path: src/Validator/BoundingBoxValidator.php + + - + message: "#^Access to an undefined property Symfony\\\\Component\\\\Validator\\\\Constraint\\:\\:\\$message\\.$#" + count: 1 + path: src/Validator/SortableValidator.php + + - + message: "#^Variable \\$fieldList in PHPDoc tag @var does not match assigned variable \\$entityFieldList\\.$#" + count: 1 + path: src/Validator/SortableValidator.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..bc0f2c3 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,7 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 5 + paths: + - src From 0cdf704d348e5929c4ab35e12246aa96fdfab2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20H=C3=BCbner?= Date: Tue, 27 Jan 2026 20:38:26 +0100 Subject: [PATCH 2/4] Add GitHub Actions CI workflow Run PHPUnit tests on PHP 8.3 and 8.4, and PHPStan static analysis on every push to main and on pull requests. Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..260e4a3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + tests: + name: Tests (PHP ${{ matrix.php }}) + runs-on: ubuntu-latest + strategy: + matrix: + php: ['8.3', '8.4'] + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist + + - name: Run tests + run: composer run tests + + phpstan: + name: PHPStan + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + coverage: none + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist + + - name: Run PHPStan + run: composer run phpstan From 9dff1efa8f4de9719021df651517983bea6ca729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20H=C3=BCbner?= Date: Tue, 27 Jan 2026 20:39:51 +0100 Subject: [PATCH 3/4] Add PHP 8.5 to CI test matrix Co-Authored-By: Claude Opus 4.5 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 260e4a3..bba355f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: ['8.3', '8.4'] + php: ['8.3', '8.4', '8.5'] steps: - uses: actions/checkout@v4 From 0379b2ad017d39b22207224813b3cc0bbd176299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20H=C3=BCbner?= Date: Tue, 27 Jan 2026 20:41:56 +0100 Subject: [PATCH 4/4] Allow unmatched baseline errors in PHPStan Some baseline errors only occur locally due to missing optional dependencies that are resolved transitively in CI. Setting reportUnmatchedIgnoredErrors to false prevents failures when baseline entries don't match. Co-Authored-By: Claude Opus 4.5 --- phpstan.neon.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index bc0f2c3..457dc0e 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -5,3 +5,4 @@ parameters: level: 5 paths: - src + reportUnmatchedIgnoredErrors: false