From cc3d7c89db91b589684c6a58bb2ce44eb33ca00c Mon Sep 17 00:00:00 2001 From: George Steel Date: Fri, 20 Jan 2023 09:22:18 +0000 Subject: [PATCH 1/2] Introduce UrlHelperInterface and mark UrlHelper as `@final` In future this will allow consumers here and elsewhere to accept the interface as a dependency instead of the concrete implementation, enabling UrlHelper to become final whilst providing a safer way of mocking and testing in user projects Signed-off-by: George Steel --- src/ConfigProvider.php | 5 +++ src/UrlHelper.php | 9 ++--- src/UrlHelperInterface.php | 75 +++++++++++++++++++++++++++++++++++++ test/ConfigProviderTest.php | 4 ++ test/UrlHelperTest.php | 42 ++------------------- 5 files changed, 91 insertions(+), 44 deletions(-) create mode 100644 src/UrlHelperInterface.php diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 31821ca..d876546 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -6,6 +6,7 @@ class ConfigProvider { + /** @return array */ public function __invoke(): array { return [ @@ -13,6 +14,7 @@ public function __invoke(): array ]; } + /** @return array */ public function getDependencies(): array { return [ @@ -26,6 +28,9 @@ public function getDependencies(): array UrlHelper::class => UrlHelperFactory::class, UrlHelperMiddleware::class => UrlHelperMiddlewareFactory::class, ], + 'aliases' => [ + UrlHelperInterface::class => UrlHelper::class, + ], ]; } } diff --git a/src/UrlHelper.php b/src/UrlHelper.php index d5f6073..98095b6 100644 --- a/src/UrlHelper.php +++ b/src/UrlHelper.php @@ -19,13 +19,10 @@ use function sprintf; /** - * @psalm-type UrlGeneratorOptions = array{ - * router?: array, - * reuse_result_params?: bool, - * reuse_query_params?: bool, - * } + * @psalm-import-type UrlGeneratorOptions from UrlHelperInterface + * @final */ -class UrlHelper +class UrlHelper implements UrlHelperInterface { /** * Regular expression used to validate fragment identifiers. diff --git a/src/UrlHelperInterface.php b/src/UrlHelperInterface.php new file mode 100644 index 0000000..fb085e6 --- /dev/null +++ b/src/UrlHelperInterface.php @@ -0,0 +1,75 @@ +, + * reuse_result_params?: bool, + * reuse_query_params?: bool, + * } + */ +interface UrlHelperInterface +{ + /** + * Generate a URL based on a given route. + * + * @param non-empty-string|null $routeName + * @param array $routeParams + * @param array $queryParams + * @param UrlGeneratorOptions $options Can have the following keys: + * - router (array): contains options to be passed to the router + * - reuse_result_params (bool): indicates if the current RouteResult parameters will be used, defaults to true + * - reuse_query_params (bool): indicates if the current query parameters will be used, defaults to false + * @throws Exception\RuntimeException For attempts to use the currently matched route but routing failed. + * @throws Exception\RuntimeException For attempts to use a matched result + * when none has been previously injected in the instance. + * @throws InvalidArgumentException For malformed fragment identifiers. + */ + public function __invoke( + ?string $routeName = null, + array $routeParams = [], + array $queryParams = [], + ?string $fragmentIdentifier = null, + array $options = [] + ): string; + + /** + * Generate a URL based on a given route. + * + * @param non-empty-string|null $routeName + * @param array $routeParams + * @param array $queryParams + * @param UrlGeneratorOptions $options Can have the following keys: + * - router (array): contains options to be passed to the router + * - reuse_result_params (bool): indicates if the current RouteResult parameters will be used, defaults to true + * - reuse_query_params (bool): indicates if the current query parameters will be used, defaults to false + * @throws Exception\RuntimeException For attempts to use the currently matched route but routing failed. + * @throws Exception\RuntimeException For attempts to use a matched result + * when none has been previously injected in the instance. + * @throws InvalidArgumentException For malformed fragment identifiers. + */ + public function generate( + ?string $routeName = null, + array $routeParams = [], + array $queryParams = [], + ?string $fragmentIdentifier = null, + array $options = [] + ): string; + + /** + * Make the current request available to the helper so that it can re-use query parameters if desired + */ + public function setRequest(ServerRequestInterface $request): void; + + /** + * Make the current routing result available to the helper so that it can re-use matched parameters if desired + */ + public function setRouteResult(RouteResult $result): void; +} diff --git a/test/ConfigProviderTest.php b/test/ConfigProviderTest.php index fd0da2c..89cd5ae 100644 --- a/test/ConfigProviderTest.php +++ b/test/ConfigProviderTest.php @@ -11,6 +11,7 @@ use Mezzio\Helper\Template\TemplateVariableContainerMiddleware; use Mezzio\Helper\UrlHelper; use Mezzio\Helper\UrlHelperFactory; +use Mezzio\Helper\UrlHelperInterface; use Mezzio\Helper\UrlHelperMiddleware; use Mezzio\Helper\UrlHelperMiddlewareFactory; use PHPUnit\Framework\TestCase; @@ -34,6 +35,9 @@ public function testReturnedArrayContainsDependencies(): void UrlHelper::class => UrlHelperFactory::class, UrlHelperMiddleware::class => UrlHelperMiddlewareFactory::class, ], + 'aliases' => [ + UrlHelperInterface::class => UrlHelper::class, + ], ], ], $config); } diff --git a/test/UrlHelperTest.php b/test/UrlHelperTest.php index 101f7e7..44f10ea 100644 --- a/test/UrlHelperTest.php +++ b/test/UrlHelperTest.php @@ -359,7 +359,7 @@ public function testBasePathIsPrependedToGeneratedPathWhenUsingRouteResult(): vo self::assertSame('/prefix/foo/baz', $helper()); } - public function testGenerateProxiesToInvokeMethod(): void + public function testGenerateAndInvokeMethodProduceTheSameResult(): void { $routeName = 'foo'; $routeParams = ['route' => 'bar']; @@ -367,44 +367,10 @@ public function testGenerateProxiesToInvokeMethod(): void $fragmentIdentifier = 'foobar'; $options = ['router' => ['foobar' => 'baz'], 'reuse_result_params' => false]; - $helper = new class ($this->router) extends UrlHelper - { - public bool $invoked = false; - - /** {@inheritDoc} */ - public function __invoke( - ?string $routeName = null, - array $routeParams = [], - array $queryParams = [], - ?string $fragmentIdentifier = null, - array $options = [] - ): string { - $this->invoked = true; - - return 'it worked'; - } - - /** {@inheritDoc} */ - public function generate( - ?string $routeName = null, - array $routeParams = [], - array $queryParams = [], - ?string $fragmentIdentifier = null, - array $options = [] - ): string { - return parent::generate($routeName, $routeParams, $queryParams, $fragmentIdentifier, $options); - } - }; - - self::assertFalse($helper->invoked); - - $generatedPath = $helper->generate($routeName, $routeParams, $queryParams, $fragmentIdentifier, $options); - - self::assertTrue($helper->invoked); - self::assertSame('it worked', $generatedPath); + $helper = $this->createHelper(); self::assertSame( - 'it worked', - $helper->__invoke($routeName, $routeParams, $queryParams, $fragmentIdentifier, $options) + $helper->__invoke($routeName, $routeParams, $queryParams, $fragmentIdentifier, $options), + $helper->generate($routeName, $routeParams, $queryParams, $fragmentIdentifier, $options), ); } From 50ee40429685c52615259a7f2190f31ac6ceb753 Mon Sep 17 00:00:00 2001 From: George Steel Date: Fri, 20 Jan 2023 09:27:07 +0000 Subject: [PATCH 2/2] Replace implementation doc blocks with `@inheritDoc` Signed-off-by: George Steel --- src/UrlHelper.php | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/UrlHelper.php b/src/UrlHelper.php index 98095b6..f79b465 100644 --- a/src/UrlHelper.php +++ b/src/UrlHelper.php @@ -41,21 +41,7 @@ public function __construct(private RouterInterface $router) { } - /** - * Generate a URL based on a given route. - * - * @param array $routeParams - * @param array $queryParams - * @param UrlGeneratorOptions $options Can have the following keys: - * - router (array): contains options to be passed to the router - * - reuse_result_params (bool): indicates if the current RouteResult - * parameters will be used, defaults to true - * @throws Exception\RuntimeException For attempts to use the currently matched - * route but routing failed. - * @throws Exception\RuntimeException For attempts to use a matched result - * when none has been previously injected in the instance. - * @throws InvalidArgumentException For malformed fragment identifiers. - */ + /** @inheritDoc */ public function __invoke( ?string $routeName = null, array $routeParams = [], @@ -109,17 +95,7 @@ public function __invoke( return $path; } - /** - * Generate a URL based on a given route. - * - * Proxies to __invoke(). - * - * @see UrlHelper::__invoke() - * - * @param array $routeParams - * @param array $queryParams - * @param UrlGeneratorOptions $options - */ + /** @inheritDoc */ public function generate( ?string $routeName = null, array $routeParams = [],