From 5c6d7beaede070641a250688d56988c4dc561a84 Mon Sep 17 00:00:00 2001 From: Alexandre Gomes Gaigalas Date: Thu, 25 Jun 2026 21:20:27 -0300 Subject: [PATCH 1/2] Migrate to respect/parameter 3.0 respect/parameter 3.0 renamed the resolver: the contract is now the `Resolver` interface and the PSR-11-backed implementation is `ContainerResolver` (the static helpers `reflectCallable()` and `acceptsType()` live on the concrete class). - composer: require respect/parameter ^3.0 (was ^1.0) - DispatchContext: instantiate `new ContainerResolver($this)`; keep `Resolver` as the interface return type of `resolver()` - Routines (Through, When, By, AuthBasic) and Routes\Callback: call the static helpers via `ContainerResolver::` Resolution behavior is unchanged: container-by-type injection does not consume a positional slot, so type-injected params (e.g. a PSR-7 request) and positional URL params resolve identically regardless of parameter order, exactly as with 1.0. --- composer.json | 2 +- src/DispatchContext.php | 3 ++- src/Routes/Callback.php | 4 ++-- src/Routines/AuthBasic.php | 6 +++--- src/Routines/By.php | 4 ++-- src/Routines/Through.php | 4 ++-- src/Routines/When.php | 4 ++-- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index 887c401..bed2458 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "psr/http-message": "^2.0", "psr/http-server-handler": "^1.0", "psr/http-server-middleware": "^1.0", - "respect/parameter": "^1.0" + "respect/parameter": "^3.0" }, "require-dev": { "nyholm/psr7": "^1.8", diff --git a/src/DispatchContext.php b/src/DispatchContext.php index bc50e54..6db3722 100644 --- a/src/DispatchContext.php +++ b/src/DispatchContext.php @@ -9,6 +9,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamFactoryInterface; +use Respect\Parameter\ContainerResolver; use Respect\Parameter\Resolver; use Respect\Rest\Handlers\ErrorHandler; use Respect\Rest\Handlers\ExceptionHandler; @@ -224,7 +225,7 @@ public function forward(AbstractRoute $route): ResponseInterface|null public function resolver(): Resolver { - return $this->resolver ??= new Resolver($this); + return $this->resolver ??= new ContainerResolver($this); } public function has(string $id): bool diff --git a/src/Routes/Callback.php b/src/Routes/Callback.php index a21a3a7..2ad701e 100644 --- a/src/Routes/Callback.php +++ b/src/Routes/Callback.php @@ -6,7 +6,7 @@ use ReflectionFunctionAbstract; use Respect\Fluent\Factories\NamespaceLookup; -use Respect\Parameter\Resolver; +use Respect\Parameter\ContainerResolver; use Respect\Rest\DispatchContext; use function array_merge; @@ -30,7 +30,7 @@ public function __construct( public function getCallbackReflection(): ReflectionFunctionAbstract { - return Resolver::reflectCallable($this->callback); + return ContainerResolver::reflectCallable($this->callback); } public function getReflection(string $method): ReflectionFunctionAbstract diff --git a/src/Routines/AuthBasic.php b/src/Routines/AuthBasic.php index 9ec198e..d2192d8 100644 --- a/src/Routines/AuthBasic.php +++ b/src/Routines/AuthBasic.php @@ -7,7 +7,7 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use ReflectionFunctionAbstract; -use Respect\Parameter\Resolver; +use Respect\Parameter\ContainerResolver; use Respect\Rest\DispatchContext; use function array_merge; @@ -63,7 +63,7 @@ private function unauthorizedResponse(DispatchContext $context): ResponseInterfa private function callbackAcceptsPsr7(): bool { - return Resolver::acceptsType( + return ContainerResolver::acceptsType( $this->getCallbackReflection(), ServerRequestInterface::class, ); @@ -71,6 +71,6 @@ private function callbackAcceptsPsr7(): bool private function getCallbackReflection(): ReflectionFunctionAbstract { - return $this->reflection ??= Resolver::reflectCallable($this->getCallback()); + return $this->reflection ??= ContainerResolver::reflectCallable($this->getCallback()); } } diff --git a/src/Routines/By.php b/src/Routines/By.php index 55e9530..c1fa7ae 100644 --- a/src/Routines/By.php +++ b/src/Routines/By.php @@ -5,7 +5,7 @@ namespace Respect\Rest\Routines; use ReflectionFunctionAbstract; -use Respect\Parameter\Resolver; +use Respect\Parameter\ContainerResolver; use Respect\Rest\DispatchContext; /** Generic routine executed before the route */ @@ -17,7 +17,7 @@ final class By extends AbstractRoutine implements ProxyableBy // phpcs:ignore Generic.NamingConventions.ConstructorName.OldStyle public function by(DispatchContext $context, array $params): mixed { - $this->reflection ??= Resolver::reflectCallable($this->getCallback()); + $this->reflection ??= ContainerResolver::reflectCallable($this->getCallback()); $args = $context->resolver()->resolve($this->reflection, $params); return ($this->getCallback())(...$args); diff --git a/src/Routines/Through.php b/src/Routines/Through.php index 814b3a3..4e496a5 100644 --- a/src/Routines/Through.php +++ b/src/Routines/Through.php @@ -5,7 +5,7 @@ namespace Respect\Rest\Routines; use ReflectionFunctionAbstract; -use Respect\Parameter\Resolver; +use Respect\Parameter\ContainerResolver; use Respect\Rest\DispatchContext; /** Generic routine executed after the route */ @@ -17,7 +17,7 @@ final class Through extends AbstractRoutine implements ProxyableThrough // phpcs:ignore Generic.NamingConventions.ConstructorName.OldStyle public function through(DispatchContext $context, array $params): mixed { - $this->reflection ??= Resolver::reflectCallable($this->getCallback()); + $this->reflection ??= ContainerResolver::reflectCallable($this->getCallback()); $args = $context->resolver()->resolve($this->reflection, $params); return ($this->getCallback())(...$args); diff --git a/src/Routines/When.php b/src/Routines/When.php index 5179964..d9c0445 100644 --- a/src/Routines/When.php +++ b/src/Routines/When.php @@ -5,7 +5,7 @@ namespace Respect\Rest\Routines; use ReflectionFunctionAbstract; -use Respect\Parameter\Resolver; +use Respect\Parameter\ContainerResolver; use Respect\Rest\DispatchContext; /** Generic routine executed before route matching */ @@ -17,7 +17,7 @@ final class When extends AbstractRoutine implements ProxyableWhen // phpcs:ignore Generic.NamingConventions.ConstructorName.OldStyle public function when(DispatchContext $context, array $params): mixed { - $this->reflection ??= Resolver::reflectCallable($this->getCallback()); + $this->reflection ??= ContainerResolver::reflectCallable($this->getCallback()); $args = $context->resolver()->resolve($this->reflection, $params); return ($this->getCallback())(...$args); From f6806d71fa6f624c672522a28e2c7835002c5612 Mon Sep 17 00:00:00 2001 From: Alexandre Gomes Gaigalas Date: Thu, 25 Jun 2026 21:20:36 -0300 Subject: [PATCH 2/2] Fix pre-existing PHPUnit 13 qa failures These issues predate the parameter migration; they surfaced when the suite moved to PHPUnit 13, which exits non-zero on warnings/deprecations and adds the `new.resultUnused` strict-rules check. - AbstractRoutineTest: extend the existing phpstan ignore on the deliberately-invalid `new Stub(...)` line to also cover `new.resultUnused` (the line exists to assert the constructor throws) - DispatchContextTest: replace deprecated `$this->any()` expectations in getMockForRoute() with a stub (`->method()`) for the no-args case and `expects($this->atLeastOnce())` for the arg-matching case, which the sole caller does invoke - RouterTest: compare the magic/concrete Callback routes by their observable state (method, pattern, arguments) instead of whole-object assertEquals, avoiding the closure-comparison warning `composer qa` is now green (phpcs, phpstan, phpunit 326 tests). --- tests/DispatchContextTest.php | 5 ++--- tests/RouterTest.php | 12 ++++++------ tests/Routines/AbstractRoutineTest.php | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/DispatchContextTest.php b/tests/DispatchContextTest.php index fe3c0ef..ad4f9dc 100644 --- a/tests/DispatchContextTest.php +++ b/tests/DispatchContextTest.php @@ -436,12 +436,11 @@ protected function getMockForRoute( if ($hasTarget) { if ($targetParams) { - $expectation = $route->expects($this->any()) + $expectation = $route->expects($this->atLeastOnce()) ->method('runTarget') ->with($targetMethod, $targetParams); } else { - $expectation = $route->expects($this->any()) - ->method('runTarget'); + $expectation = $route->method('runTarget'); } if (is_callable($target)) { diff --git a/tests/RouterTest.php b/tests/RouterTest.php index be7f93c..e878371 100644 --- a/tests/RouterTest.php +++ b/tests/RouterTest.php @@ -115,9 +115,9 @@ public function testMagicConstructorCanCreateCallbackRoutes(): void 'When there are no arguments the Routes\Callback should have none as well', ); - self::assertEquals( - $callbackRoute, - $concreteCallbackRoute, + self::assertSame( + [$concreteCallbackRoute->method, $concreteCallbackRoute->pattern, $concreteCallbackRoute->arguments], + [$callbackRoute->method, $callbackRoute->pattern, $callbackRoute->arguments], 'The magic and concrete instances of Routes\Callback should be equivalent', ); } @@ -147,9 +147,9 @@ public function testMagicConstructorCanCreateCallbackRoutesWithExtraParams(): vo 'The "extra" appended to the magic constructor should be present on the arguments list', ); - self::assertEquals( - $callbackRoute, - $concreteCallbackRoute, + self::assertSame( + [$concreteCallbackRoute->method, $concreteCallbackRoute->pattern, $concreteCallbackRoute->arguments], + [$callbackRoute->method, $callbackRoute->pattern, $callbackRoute->arguments], 'The magic and concrete instances of Routes\Callback should be equivalent', ); } diff --git a/tests/Routines/AbstractRoutineTest.php b/tests/Routines/AbstractRoutineTest.php index d8bf4de..19bfebd 100644 --- a/tests/Routines/AbstractRoutineTest.php +++ b/tests/Routines/AbstractRoutineTest.php @@ -42,6 +42,6 @@ static function () { public function test_invalid_constructor_arguments(): void { self::expectException(TypeError::class); - new Stub('this_function_name_does_not_exist'); // @phpstan-ignore argument.type + new Stub('this_function_name_does_not_exist'); // @phpstan-ignore argument.type, new.resultUnused } }