From 5578dc5ccfdc877a58b5e9c9c5f84acb434587d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orlando=20Th=C3=B6ny?= Date: Mon, 17 Nov 2025 16:58:30 +0100 Subject: [PATCH 1/2] fix(deprecation warning): str_replace(): Passing null to parameter #3 ($subject) Remaining self deprecation notices (1) 1x: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated 1x in RateLimitAnnotationListenerTest::testDispatchIsCalledIfThePathLimitProcessorReturnsARateLimit from Noxlogic\RateLimitBundle\Tests\EventListener --- DependencyInjection/Configuration.php | 9 +-- .../DependencyInjection/ConfigurationTest.php | 58 ++++++++++++------- Util/PathLimitProcessor.php | 13 ++--- phpstan-baseline.neon | 18 ------ 4 files changed, 48 insertions(+), 50 deletions(-) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index dc4a2c5..b16a16e 100755 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -26,7 +26,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->canBeDisabled() ->children() ->enumNode('storage_engine') - ->values(array('redis','memcache','doctrine', 'php_redis', 'php_redis_cluster', 'simple_cache', 'cache')) + ->values(['redis','memcache','doctrine', 'php_redis', 'php_redis_cluster', 'simple_cache', 'cache']) ->defaultValue('redis') ->info('The storage engine where all the rates will be stored') ->end() @@ -109,19 +109,20 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->end() ->arrayNode('path_limits') - ->defaultValue(array()) + ->defaultValue([]) ->info('Rate limits for paths') ->prototype('array') ->children() ->scalarNode('path') ->isRequired() + ->cannotBeEmpty() ->end() ->arrayNode('methods') ->prototype('enum') - ->values(array('*', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH')) + ->values(['*', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']) ->end() ->requiresAtLeastOneElement() - ->defaultValue(array('*')) + ->defaultValue(['*']) ->end() ->integerNode('limit') ->isRequired() diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index d09931e..ca8d5eb 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -7,29 +7,23 @@ use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Processor; -/** - * ConfigurationTest - */ class ConfigurationTest extends WebTestCase { - /** - * @var Processor - */ - private $processor; + private Processor $processor; public function setUp():void { $this->processor = new Processor(); } - private function getConfigs(array $configArray) + private function getConfigs(array $configArray): array { $configuration = new Configuration(); return $this->processor->processConfiguration($configuration, array($configArray)); } - public function testUnconfiguredConfiguration() + public function testUnconfiguredConfiguration(): void { $configuration = $this->getConfigs(array()); @@ -59,7 +53,7 @@ public function testUnconfiguredConfiguration() ), $configuration); } - public function testDisabledConfiguration() + public function testDisabledConfiguration(): void { $configuration = $this->getConfigs(array('enabled' => false)); @@ -67,7 +61,7 @@ public function testDisabledConfiguration() $this->assertFalse($configuration['enabled']); } - public function testPathLimitConfiguration() + public function testPathLimitConfiguration(): void { $pathLimits = array( 'api' => array( @@ -86,7 +80,7 @@ public function testPathLimitConfiguration() $this->assertEquals($pathLimits, $configuration['path_limits']); } - public function testMultiplePathLimitConfiguration() + public function testMultiplePathLimitConfiguration(): void { $pathLimits = array( 'api' => array( @@ -111,7 +105,7 @@ public function testMultiplePathLimitConfiguration() $this->assertEquals($pathLimits, $configuration['path_limits']); } - public function testDefaultPathLimitMethods() + public function testDefaultPathLimitMethods(): void { $pathLimits = array( 'api' => array( @@ -137,28 +131,50 @@ public function testDefaultPathLimitMethods() $this->assertEquals($pathLimits, $configuration['path_limits']); } - public function testMustBeBasedOnExceptionClass() + public function testMustBeBasedOnExceptionClass(): void + { + $this->expectException(InvalidConfigurationException::class); + $this->getConfigs(array('rate_response_exception' => '\StdClass')); + } + + /** + * @testWith [""] + * [null] + */ + public function testEmptyPathIsNotAllowed(mixed $path): void { + $pathLimits = [ + 'api' => [ + 'path' => $path, + 'methods' => ['GET'], + 'limit' => 200, + 'period' => 10 + ], + ]; + $this->expectException(InvalidConfigurationException::class); - $configuration = $this->getConfigs(array('rate_response_exception' => '\StdClass')); + + $this->getConfigs(array( + 'path_limits' => $pathLimits + )); } /** * */ - public function testMustBeBasedOnExceptionClass2() + public function testMustBeBasedOnExceptionClass2(): void { - $configuration = $this->getConfigs(array('rate_response_exception' => '\InvalidArgumentException')); + $this->getConfigs(array('rate_response_exception' => '\InvalidArgumentException')); # no exception triggered is ok. - $this->assertTrue(true); + $this->expectNotToPerformAssertions(); } - public function testMustBeBasedOnExceptionOrNull() + public function testMustBeBasedOnExceptionOrNull(): void { - $configuration = $this->getConfigs(array('rate_response_exception' => null)); + $this->getConfigs(array('rate_response_exception' => null)); # no exception triggered is ok. - $this->assertTrue(true); + $this->expectNotToPerformAssertions(); } } diff --git a/Util/PathLimitProcessor.php b/Util/PathLimitProcessor.php index 3846f8b..110f535 100644 --- a/Util/PathLimitProcessor.php +++ b/Util/PathLimitProcessor.php @@ -8,12 +8,11 @@ class PathLimitProcessor { - private array $pathLimits; - - public function __construct(array $pathLimits) + /** + * @param array, limit: int<-1, max>, period: positive-int}> $pathLimits + */ + public function __construct(private array $pathLimits) { - $this->pathLimits = $pathLimits; - // Clean up any extra slashes from the config foreach ($this->pathLimits as &$pathLimit) { $pathLimit['path'] = trim($pathLimit['path'], '/'); @@ -21,7 +20,7 @@ public function __construct(array $pathLimits) // Order the configs so that the most specific paths // are matched first - usort($this->pathLimits, static function($a, $b) { + usort($this->pathLimits, static function($a, $b): int { return substr_count($b['path'], '/') - substr_count($a['path'], '/'); }); } @@ -44,7 +43,7 @@ public function getRateLimit(Request $request): ?RateLimit return null; } - public function getMatchedPath(Request $request) + public function getMatchedPath(Request $request): string { $path = trim($request->getPathInfo(), '/'); $method = $request->getMethod(); diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f3cd5f7..34a01ef 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -384,18 +384,6 @@ parameters: count: 1 path: Service/Storage/StorageInterface.php - - - message: '#^Method Noxlogic\\RateLimitBundle\\Util\\PathLimitProcessor\:\:__construct\(\) has parameter \$pathLimits with no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: Util/PathLimitProcessor.php - - - - message: '#^Method Noxlogic\\RateLimitBundle\\Util\\PathLimitProcessor\:\:getMatchedPath\(\) has no return type specified\.$#' - identifier: missingType.return - count: 1 - path: Util/PathLimitProcessor.php - - message: '#^Method Noxlogic\\RateLimitBundle\\Util\\PathLimitProcessor\:\:methodMatched\(\) has parameter \$expectedMethods with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -437,9 +425,3 @@ parameters: identifier: missingType.parameter count: 1 path: Util/PathLimitProcessor.php - - - - message: '#^Property Noxlogic\\RateLimitBundle\\Util\\PathLimitProcessor\:\:\$pathLimits type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: Util/PathLimitProcessor.php From 72545baadb06ce93aeada24c50db669fe2a3bf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orlando=20Th=C3=B6ny?= Date: Mon, 17 Nov 2025 17:17:03 +0100 Subject: [PATCH 2/2] fix(deprecation warning): str_replace(): Passing null to parameter #3 ($subject) Remaining self deprecation notices (1) 1x: str_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated 1x in RateLimitAnnotationListenerTest::testDispatchIsCalledIfThePathLimitProcessorReturnsARateLimit from Noxlogic\RateLimitBundle\Tests\EventListener --- Tests/DependencyInjection/ConfigurationTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index ca8d5eb..b881ce4 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -154,9 +154,9 @@ public function testEmptyPathIsNotAllowed(mixed $path): void $this->expectException(InvalidConfigurationException::class); - $this->getConfigs(array( + $this->getConfigs([ 'path_limits' => $pathLimits - )); + ]); } /**