diff --git a/CHANGELOG.md b/CHANGELOG.md index 3189bc8..11e5e89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,22 @@ All notable changes to this project will be documented in this file, in reverse - [#4](https://github.com/zendframework/zend-expressive-zendviewrenderer/pull/) Allow rendering view models via render +- [#9](https://github.com/zendframework/zend-expressive-zendviewrenderer/pull/) + updates `UrlHelper` to implement `Zend\Expressive\Template\RouteResultObserverInterface`, + and the `update()` method it defines. This allows it to observer the + application for the `RouteResult` and store it for later URI generation. + To accomplish this, the following additional changes were made: + - `Zend\Expressive\ZendView\UrlHelperFactory` was added, for creating the + `UrlHelper` instance. This should be registered with the application service + container. + - `Zend\Expressive\ZendView\ZendViewRendererFactory` was updated to look for + the `Zend\Expressive\ZendView\UrlHelper` service in the application service + container, and use it to seed the `HelperManager` when available. + - `Zend\Expressive\ZendView\ApplicationUrlDelegatorFactory` was created; when + registered as a delegator factory with the `Zend\Expressive\Application` + service, it will pull the `UrlHelper` and attach it as a route result + observer to the `Application` instance. Documentation was also provided for + creating a Pimple extension for accomplishing this. ### Deprecated diff --git a/composer.json b/composer.json index abc3484..e118561 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "require": { "php": ">=5.5", "container-interop/container-interop": "^1.1", - "zendframework/zend-expressive": "^1.0@rc", + "zendframework/zend-expressive": "~1.0.0-dev@dev", "zendframework/zend-filter": "^2.5", "zendframework/zend-i18n": "^2.5", "zendframework/zend-servicemanager": "^2.5", diff --git a/src/ApplicationUrlDelegatorFactory.php b/src/ApplicationUrlDelegatorFactory.php new file mode 100644 index 0000000..fd1c16b --- /dev/null +++ b/src/ApplicationUrlDelegatorFactory.php @@ -0,0 +1,33 @@ +has(UrlHelper::class)) { + $application->attachRouteResultObserver($container->get(UrlHelper::class)); + } + return $application; + } +} diff --git a/src/UrlHelper.php b/src/UrlHelper.php index 2607051..40f103e 100644 --- a/src/UrlHelper.php +++ b/src/UrlHelper.php @@ -10,9 +10,10 @@ use Zend\Expressive\Exception; use Zend\Expressive\Router\RouterInterface; use Zend\Expressive\Router\RouteResult; +use Zend\Expressive\Router\RouteResultObserverInterface; use Zend\View\Helper\AbstractHelper; -class UrlHelper extends AbstractHelper +class UrlHelper extends AbstractHelper implements RouteResultObserverInterface { /** * @var RouteResult @@ -62,6 +63,14 @@ public function __invoke($route = null, $params = []) return $this->router->generateUri($route, $params); } + /** + * {@inheritDoc} + */ + public function update(RouteResult $result) + { + $this->result = $result; + } + /** * @param RouteResult $result */ diff --git a/src/UrlHelperFactory.php b/src/UrlHelperFactory.php new file mode 100644 index 0000000..9047030 --- /dev/null +++ b/src/UrlHelperFactory.php @@ -0,0 +1,27 @@ +get(RouterInterface::class)); + } +} diff --git a/src/ZendViewRendererFactory.php b/src/ZendViewRendererFactory.php index ccf4bde..d68677a 100644 --- a/src/ZendViewRendererFactory.php +++ b/src/ZendViewRendererFactory.php @@ -103,6 +103,9 @@ private function injectHelpers(PhpRenderer $renderer, ContainerInterface $contai : new HelperPluginManager(); $helpers->setFactory('url', function () use ($container) { + if ($container->has(UrlHelper::class)) { + return $container->get(UrlHelper::class); + } return new UrlHelper($container->get(RouterInterface::class)); }); $helpers->setInvokableClass('serverurl', ServerUrlHelper::class); diff --git a/test/ApplicationUrlDelegatorFactoryTest.php b/test/ApplicationUrlDelegatorFactoryTest.php new file mode 100644 index 0000000..22202b0 --- /dev/null +++ b/test/ApplicationUrlDelegatorFactoryTest.php @@ -0,0 +1,42 @@ +prophesize(UrlHelper::class); + $application = $this->prophesize(Application::class); + $application->attachRouteResultObserver($urlHelper->reveal())->shouldBeCalled(); + $applicationCallback = function () use ($application) { + return $application->reveal(); + }; + + $container = $this->prophesize(ServiceLocatorInterface::class); + $container->has(UrlHelper::class)->willReturn(true); + $container->get(UrlHelper::class)->willReturn($urlHelper->reveal()); + + $delegator = new ApplicationUrlDelegatorFactory(); + $test = $delegator->createDelegatorWithName( + $container->reveal(), + Application::class, + Application::class, + $applicationCallback + ); + $this->assertSame($application->reveal(), $test); + } +} diff --git a/test/UrlHelperTest.php b/test/UrlHelperTest.php index 37c4e06..d2dd0d5 100644 --- a/test/UrlHelperTest.php +++ b/test/UrlHelperTest.php @@ -14,6 +14,7 @@ use Zend\Expressive\Exception; use Zend\Expressive\Router\RouterInterface; use Zend\Expressive\Router\RouteResult; +use Zend\Expressive\Router\RouteResultObserverInterface; use Zend\Expressive\ZendView\UrlHelper; class UrlHelperTest extends TestCase @@ -134,4 +135,18 @@ public function testProvidedParametersOverrideAnyPresentInARouteResultWhenGenera $this->assertEquals('URL', $helper('resource', ['id' => 2])); } + + public function testIsARouteResultObserver() + { + $helper = $this->createHelper(); + $this->assertInstanceOf(RouteResultObserverInterface::class, $helper); + } + + public function testUpdateMethodSetsRouteResultProperty() + { + $result = $this->prophesize(RouteResult::class); + $helper = $this->createHelper(); + $helper->update($result->reveal()); + $this->assertAttributeSame($result->reveal(), 'result', $helper); + } } diff --git a/test/ZendViewRendererFactoryTest.php b/test/ZendViewRendererFactoryTest.php index d82fbe8..c11ea6c 100644 --- a/test/ZendViewRendererFactoryTest.php +++ b/test/ZendViewRendererFactoryTest.php @@ -213,6 +213,7 @@ public function testInjectsCustomHelpersIntoHelperManager() $router = $this->prophesize(RouterInterface::class)->reveal(); $this->container->has('config')->willReturn(false); $this->container->has(HelperPluginManager::class)->willReturn(false); + $this->container->has(UrlHelper::class)->willReturn(false); $this->container->has(RouterInterface::class)->willReturn(true); $this->container->get(RouterInterface::class)->willReturn($router); $factory = new ZendViewRendererFactory(); @@ -234,6 +235,7 @@ public function testWillUseHelperManagerFromContainer() $this->container->has('config')->willReturn(false); $this->container->has(RouterInterface::class)->willReturn(true); $this->container->get(RouterInterface::class)->willReturn($router); + $this->container->has(UrlHelper::class)->willReturn(false); $helpers = new HelperPluginManager(); $this->container->has(HelperPluginManager::class)->willReturn(true); @@ -257,4 +259,23 @@ public function testInjectsCustomHelpersIntoHelperManagerFromContainer(HelperPlu $this->assertInstanceOf(UrlHelper::class, $helpers->get('url')); $this->assertInstanceOf(ServerUrlHelper::class, $helpers->get('serverurl')); } + + public function testWillUseUrlHelperFromContainerWhenAvailable() + { + $urlHelper = $this->prophesize(UrlHelper::class)->reveal(); + $router = $this->prophesize(RouterInterface::class)->reveal(); + $this->container->has('config')->willReturn(false); + $this->container->has(HelperPluginManager::class)->willReturn(false); + $this->container->has(UrlHelper::class)->willReturn(true); + $this->container->get(UrlHelper::class)->willReturn($urlHelper); + $this->container->has(RouterInterface::class)->willReturn(true); + $this->container->get(RouterInterface::class)->willReturn($router); + $factory = new ZendViewRendererFactory(); + $view = $factory($this->container->reveal()); + + $renderer = $this->fetchPhpRenderer($view); + $helpers = $renderer->getHelperPluginManager(); + $this->assertTrue($helpers->has('url')); + $this->assertSame($urlHelper, $helpers->get('url')); + } }