From 6958ec169f31e3396a72d1811cb85d4f5d5c5808 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Tue, 23 Dec 2025 12:49:02 +0100 Subject: [PATCH 1/3] feat: migrate PHPStan 1 => 2 --- composer.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b02503e..19e8527 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "nyholm/nsa": "^1.3", "nyholm/psr7": "^1.8", "nyholm/symfony-bundle-test": "^3.1", - "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan": "^2.1", "psr/http-client": "^1.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", "symfony/cache": "^6.4 || ^7.0 || ^8.0", @@ -78,7 +78,8 @@ } }, "scripts": { - "test": "SYMFONY_DEPRECATIONS_HELPER=ignoreFile='./tests/baseline-ignore' vendor/bin/simple-phpunit --testsuite main" + "test": "SYMFONY_DEPRECATIONS_HELPER=ignoreFile='./tests/baseline-ignore' vendor/bin/simple-phpunit --testsuite main", + "phpstan": "vendor/bin/phpstan --memory-limit=1024m" }, "config": { "allow-plugins": { From 55afe873fa5007500b9162a5ec37acc09c923472 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Tue, 23 Dec 2025 14:58:35 +0100 Subject: [PATCH 2/3] feat: migrate PHPStan 1 => 2 --- composer.json | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index 19e8527..d26c568 100644 --- a/composer.json +++ b/composer.json @@ -15,8 +15,8 @@ ], "require": { "php": "^8.1", - "geocoder-php/plugin": "^1.5", - "php-http/discovery": "^1.14", + "geocoder-php/plugin": "^1.6", + "php-http/discovery": "^1.20", "symfony/console": "^6.4 || ^7.0 || ^8.0", "symfony/framework-bundle": "^6.4 || ^7.0 || ^8.0", "symfony/options-resolver": "^6.4 || ^7.0 || ^8.0", @@ -25,27 +25,27 @@ "require-dev": { "doctrine/doctrine-bundle": "^2.18 || ^3.0", "doctrine/orm": "^2.20 || ^3.0", - "fakerphp/faker": "^1.20", - "friendsofphp/php-cs-fixer": "^3.13", + "fakerphp/faker": "^1.24", + "friendsofphp/php-cs-fixer": "^3.92", "geocoder-php/algolia-places-provider": "^0.5", - "geocoder-php/arcgis-online-provider": "^4.4", - "geocoder-php/bing-maps-provider": "^4.3", - "geocoder-php/cache-provider": "^4.4.0", - "geocoder-php/chain-provider": "^4.5", - "geocoder-php/free-geoip-provider": "^4.5", - "geocoder-php/geo-plugin-provider": "^4.3", - "geocoder-php/geoip2-provider": "^4.3", - "geocoder-php/geonames-provider": "^4.4", - "geocoder-php/google-maps-places-provider": "^1.4", - "geocoder-php/google-maps-provider": "^4.7", + "geocoder-php/arcgis-online-provider": "^4.5", + "geocoder-php/bing-maps-provider": "^4.4", + "geocoder-php/cache-provider": "^4.5.0", + "geocoder-php/chain-provider": "^4.6", + "geocoder-php/free-geoip-provider": "^4.6", + "geocoder-php/geo-plugin-provider": "^4.4", + "geocoder-php/geoip2-provider": "^4.4", + "geocoder-php/geonames-provider": "^4.5", + "geocoder-php/google-maps-places-provider": "^1.5", + "geocoder-php/google-maps-provider": "^4.8", "geocoder-php/here-provider": "^0.8", "geocoder-php/host-ip-provider": "^4.5", - "geocoder-php/ip-info-db-provider": "^4.3", + "geocoder-php/ip-info-db-provider": "^4.4", "geocoder-php/ip-info-provider": "^0.5", "geocoder-php/ipstack-provider": "^0.5", - "geocoder-php/locationiq-provider": "^1.4", - "geocoder-php/mapbox-provider": "^1.4", - "geocoder-php/mapquest-provider": "^4.3", + "geocoder-php/locationiq-provider": "^1.5", + "geocoder-php/mapbox-provider": "^1.5", + "geocoder-php/mapquest-provider": "^4.4", "geocoder-php/maxmind-provider": "^4.5", "geocoder-php/nominatim-provider": "^5.8", "geocoder-php/open-cage-provider": "^4.7", From 0bfee999ddac3a5d9a988f964e9f99255533b4bc Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Tue, 23 Dec 2025 15:23:58 +0100 Subject: [PATCH 3/3] feat: migrate PHPStan 1 => 2 --- composer.json | 3 +- phpstan-baseline.php | 92 ++++++++++++++--------------- phpstan.dist.neon | 1 + src/Plugin/FakeIpPlugin.php | 2 +- src/ProviderFactory/HereFactory.php | 4 -- 5 files changed, 50 insertions(+), 52 deletions(-) diff --git a/composer.json b/composer.json index d26c568..afc09e2 100644 --- a/composer.json +++ b/composer.json @@ -79,7 +79,8 @@ }, "scripts": { "test": "SYMFONY_DEPRECATIONS_HELPER=ignoreFile='./tests/baseline-ignore' vendor/bin/simple-phpunit --testsuite main", - "phpstan": "vendor/bin/phpstan --memory-limit=1024m" + "phpstan": "vendor/bin/phpstan analyse --memory-limit=1024m", + "phpstan-baseline": "vendor/bin/phpstan analyse --generate-baseline phpstan-baseline.php --memory-limit=1024m" }, "config": { "allow-plugins": { diff --git a/phpstan-baseline.php b/phpstan-baseline.php index f609d21..4c75908 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -4,206 +4,206 @@ $ignoreErrors = []; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$name of method Geocoder\\\\ProviderAggregator\\:\\:using\\(\\) expects string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/Command/GeocodeCommand.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$string of function strtolower expects string, string\\|null given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/Command/GeocodeCommand.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$text of static method Geocoder\\\\Query\\\\GeocodeQuery\\:\\:create\\(\\) expects string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/Command/GeocodeCommand.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#3 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/Command/GeocodeCommand.php', ]; $ignoreErrors[] = [ - // identifier: foreach.nonIterable + 'message' => '#^Method Bazinga\\\\GeocoderBundle\\\\DataCollector\\\\GeocoderDataCollector\\:\\:getProviderQueries\\(\\) should return list\\ but returns array\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__.'/src/DataCollector/GeocoderDataCollector.php', +]; +$ignoreErrors[] = [ 'message' => '#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#', + 'identifier' => 'foreach.nonIterable', 'count' => 3, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: offsetAccess.nonOffsetAccessible + 'message' => '#^Binary operation "\\." between \'bazinga_geocoder…\' and mixed results in an error\\.$#', + 'identifier' => 'binaryOp.invalid', + 'count' => 1, + 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', +]; +$ignoreErrors[] = [ 'message' => '#^Cannot access offset \'aliases\' on mixed\\.$#', + 'identifier' => 'offsetAccess.nonOffsetAccessible', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: offsetAccess.nonOffsetAccessible 'message' => '#^Cannot access offset \'enabled\' on mixed\\.$#', + 'identifier' => 'offsetAccess.nonOffsetAccessible', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: offsetAccess.nonOffsetAccessible 'message' => '#^Cannot access offset \'factory\' on mixed\\.$#', + 'identifier' => 'offsetAccess.nonOffsetAccessible', 'count' => 5, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: offsetAccess.nonOffsetAccessible 'message' => '#^Cannot access offset \'id\' on mixed\\.$#', + 'identifier' => 'offsetAccess.nonOffsetAccessible', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: offsetAccess.nonOffsetAccessible 'message' => '#^Cannot access offset \'options\' on mixed\\.$#', + 'identifier' => 'offsetAccess.nonOffsetAccessible', 'count' => 4, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: offsetAccess.nonOffsetAccessible 'message' => '#^Cannot access offset \'reference\' on mixed\\.$#', + 'identifier' => 'offsetAccess.nonOffsetAccessible', 'count' => 2, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: staticMethod.nonObject 'message' => '#^Cannot call static method validate\\(\\) on mixed\\.$#', + 'identifier' => 'staticMethod.nonObject', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: cast.string 'message' => '#^Cannot cast mixed to string\\.$#', + 'identifier' => 'cast.string', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$alias of method Symfony\\\\Component\\\\DependencyInjection\\\\ContainerBuilder\\:\\:setAlias\\(\\) expects string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$callback of function array_map expects \\(callable\\(mixed\\)\\: mixed\\)\\|null, Closure\\(string\\)\\: Symfony\\\\Component\\\\DependencyInjection\\\\Reference given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$factoryServiceId of static method Bazinga\\\\GeocoderBundle\\\\DependencyInjection\\\\Compiler\\\\FactoryValidatorPass\\:\\:addFactoryServiceId\\(\\) expects non\\-empty\\-string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$id of class Symfony\\\\Component\\\\DependencyInjection\\\\Reference constructor expects string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$id of method Symfony\\\\Component\\\\DependencyInjection\\\\ContainerBuilder\\:\\:getDefinition\\(\\) expects string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$object_or_class of function class_implements expects object\\|string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type - 'message' => '#^Parameter \\#1 \\$options of method Bazinga\\\\GeocoderBundle\\\\DependencyInjection\\\\BazingaGeocoderExtension\\:\\:findReferences\\(\\) expects array\\, mixed given\\.$#', + 'message' => '#^Parameter \\#1 \\$options of method Bazinga\\\\GeocoderBundle\\\\DependencyInjection\\\\BazingaGeocoderExtension\\:\\:findReferences\\(\\) expects array\\, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 2, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$string of function ltrim expects string, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#2 \\$array of function array_key_exists expects array, array\\|bool\\|float\\|int\\|string\\|UnitEnum\\|null given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type - 'message' => '#^Parameter \\#2 \\$config of method Bazinga\\\\GeocoderBundle\\\\DependencyInjection\\\\BazingaGeocoderExtension\\:\\:configureProviderPlugins\\(\\) expects array, mixed given\\.$#', + 'message' => '#^Parameter \\#2 \\$config of method Bazinga\\\\GeocoderBundle\\\\DependencyInjection\\\\BazingaGeocoderExtension\\:\\:configureProviderPlugins\\(\\) expects array\\, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#2 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, mixed given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: encapsedStringPart.nonString 'message' => '#^Part \\$providerName \\(mixed\\) of encapsed string cannot be cast to string\\.$#', + 'identifier' => 'encapsedStringPart.nonString', 'count' => 1, 'path' => __DIR__.'/src/DependencyInjection/BazingaGeocoderExtension.php', ]; $ignoreErrors[] = [ - // identifier: method.nonObject 'message' => '#^Cannot call method getLatitude\\(\\) on Geocoder\\\\Model\\\\Coordinates\\|null\\.$#', + 'identifier' => 'method.nonObject', 'count' => 1, 'path' => __DIR__.'/src/Doctrine/ORM/GeocodeEntityListener.php', ]; $ignoreErrors[] = [ - // identifier: method.nonObject 'message' => '#^Cannot call method getLongitude\\(\\) on Geocoder\\\\Model\\\\Coordinates\\|null\\.$#', + 'identifier' => 'method.nonObject', 'count' => 1, 'path' => __DIR__.'/src/Doctrine/ORM/GeocodeEntityListener.php', ]; $ignoreErrors[] = [ - // identifier: argument.missing - 'message' => '#^Missing parameter \\$provider \\(string\\) in call to Bazinga\\\\GeocoderBundle\\\\Mapping\\\\ClassMetadata constructor\\.$#', - 'count' => 1, - 'path' => __DIR__.'/src/Mapping/Driver/AttributeDriver.php', -]; -$ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$text of method Geocoder\\\\Query\\\\GeocodeQuery\\:\\:withText\\(\\) expects string, string\\|null given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/Plugin/FakeIpPlugin.php', ]; $ignoreErrors[] = [ - // identifier: argument.type - 'message' => '#^Parameter \\#2 \\$replace of function str_replace expects array\\|string, string\\|null given\\.$#', - 'count' => 1, - 'path' => __DIR__.'/src/Plugin/FakeIpPlugin.php', -]; -$ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$accountId of class GeoIp2\\\\WebService\\\\Client constructor expects int, int\\|null given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/ProviderFactory/GeoIP2Factory.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$filename of class GeoIp2\\\\Database\\\\Reader constructor expects string, string\\|null given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/ProviderFactory/GeoIP2Factory.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#1 \\$geoIpProvider of class Geocoder\\\\Provider\\\\GeoIP2\\\\GeoIP2Adapter constructor expects GeoIp2\\\\ProviderInterface, GeoIp2\\\\ProviderInterface\\|null given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/ProviderFactory/GeoIP2Factory.php', ]; $ignoreErrors[] = [ - // identifier: argument.type 'message' => '#^Parameter \\#2 \\$licenseKey of class GeoIp2\\\\WebService\\\\Client constructor expects string, string\\|null given\\.$#', + 'identifier' => 'argument.type', 'count' => 1, 'path' => __DIR__.'/src/ProviderFactory/GeoIP2Factory.php', ]; diff --git a/phpstan.dist.neon b/phpstan.dist.neon index b03a213..460aa57 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -8,3 +8,4 @@ parameters: - src/ #- tests/ level: 9 + treatPhpDocTypesAsCertain: false diff --git a/src/Plugin/FakeIpPlugin.php b/src/Plugin/FakeIpPlugin.php index 8909d8a..35f9809 100644 --- a/src/Plugin/FakeIpPlugin.php +++ b/src/Plugin/FakeIpPlugin.php @@ -54,7 +54,7 @@ public function handleQuery(Query $query, callable $next, callable $first) $replacement = $this->faker->ipv4(); } - if (null !== $this->needle && '' !== $this->needle) { + if (null !== $this->needle && '' !== $this->needle && $replacement) { $text = str_replace($this->needle, $replacement, $query->getText(), $count); if ($count > 0) { diff --git a/src/ProviderFactory/HereFactory.php b/src/ProviderFactory/HereFactory.php index 01dab55..64b80b0 100644 --- a/src/ProviderFactory/HereFactory.php +++ b/src/ProviderFactory/HereFactory.php @@ -36,10 +36,6 @@ protected function getProvider(array $config): Provider $httpClient = $config['http_client'] ?? $this->httpClient ?? Psr18ClientDiscovery::find(); if (!empty($config['app_key'])) { - if (!method_exists(Here::class, 'createUsingApiKey')) { - throw new \InvalidArgumentException('Here provider has no support for `creatingUsingApiKey` method.'); - } - return Here::createUsingApiKey($httpClient, $config['app_key'], $config['use_cit']); }