diff --git a/src/Annotation/TwigRedirectPath.php b/src/Annotation/TwigRedirectPath.php new file mode 100644 index 0000000..79bdd2e --- /dev/null +++ b/src/Annotation/TwigRedirectPath.php @@ -0,0 +1,19 @@ +bindTwigEnvironment(); $this->bindTwigPaths(); $this->bindTwigOptions(); + $this->bindTwigRedirectPath(); } private function bindRender() @@ -116,6 +118,11 @@ private function bindTwigOptions() $this->bind()->annotatedWith(TwigOptions::class)->toProvider(OptionProvider::class); } + private function bindTwigRedirectPath() + { + $this->bind()->annotatedWith(TwigRedirectPath::class)->toInstance('/redirect/redirect.html.twig'); + } + private function isNotEmpty($var) { return \is_array($var) && ! empty($var); diff --git a/src/TwigRenderer.php b/src/TwigRenderer.php index 62f8921..4953481 100644 --- a/src/TwigRenderer.php +++ b/src/TwigRenderer.php @@ -9,6 +9,7 @@ use BEAR\Resource\Code; use BEAR\Resource\RenderInterface; use BEAR\Resource\ResourceObject; +use Madapaja\TwigModule\Annotation\TwigRedirectPath; use Ray\Aop\WeavedInterface; use Twig\Environment; use Twig\Error\LoaderError; @@ -29,14 +30,23 @@ class TwigRenderer implements RenderInterface */ public $twig; + /** + * @var string + */ + private $redirectPage; + /** * @var TemplateFinderInterface */ private $templateFinder; - public function __construct(Environment $twig, TemplateFinderInterface $templateFinder = null) + /** + * @TwigRedirectPath("redirectPage") + */ + public function __construct(Environment $twig, string $redirectPage, TemplateFinderInterface $templateFinder = null) { $this->twig = $twig; + $this->redirectPage = $redirectPage; $this->templateFinder = $templateFinder ?: new TemplateFinder; } @@ -46,7 +56,14 @@ public function __construct(Environment $twig, TemplateFinderInterface $template public function render(ResourceObject $ro) { $this->setContentType($ro); - $ro->view = $this->isNoContent($ro) ? '' : $this->renderView($ro); + + if ($this->isNoContent($ro)) { + $ro->view = ''; + } elseif ($this->isRedirect($ro)) { + $ro->view = $this->renderRedirectView($ro); + } else { + $ro->view = $this->renderView($ro); + } return $ro->view; } @@ -65,6 +82,13 @@ private function renderView(ResourceObject $ro) return $template ? $template->render($this->buildBody($ro)) : ''; } + private function renderRedirectView(ResourceObject $ro) + { + $url = $ro->headers['Location']; + + return $this->twig->render($this->redirectPage, ['url' => $url]); + } + /** * @return null|\Twig\TemplateWrapper */ @@ -84,6 +108,17 @@ private function isNoContent(ResourceObject $ro) : bool return $ro->code === Code::NO_CONTENT || $ro->view === ''; } + private function isRedirect(ResourceObject $ro) : bool + { + return \in_array($ro->code, [ + Code::MOVED_PERMANENTLY, + Code::FOUND, + Code::SEE_OTHER, + Code::TEMPORARY_REDIRECT, + Code::PERMANENT_REDIRECT, + ], true) && isset($ro->headers['Location']); + } + private function loadTemplate(ResourceObject $ro) : TemplateWrapper { $loader = $this->twig->getLoader(); diff --git a/tests/Fake/src/Resource/Page/Redirect.html.twig b/tests/Fake/src/Resource/Page/Redirect.html.twig new file mode 100644 index 0000000..77f5bf4 --- /dev/null +++ b/tests/Fake/src/Resource/Page/Redirect.html.twig @@ -0,0 +1 @@ +foo is {{ foo }}. diff --git a/tests/Fake/src/Resource/Page/Redirect.php b/tests/Fake/src/Resource/Page/Redirect.php new file mode 100644 index 0000000..48d1749 --- /dev/null +++ b/tests/Fake/src/Resource/Page/Redirect.php @@ -0,0 +1,30 @@ +body = [ + 'foo' => 'bar', + ]; + + return $this; + } + + public function onPost() + { + $this->code = Code::FOUND; + $this->headers['Location'] = '/path/to/baz'; + + return $this; + } +} diff --git a/tests/Fake/src/Resource/redirect/redirect.html.twig b/tests/Fake/src/Resource/redirect/redirect.html.twig new file mode 100644 index 0000000..da82d89 --- /dev/null +++ b/tests/Fake/src/Resource/redirect/redirect.html.twig @@ -0,0 +1,11 @@ + + + + + + Redirecting to {{ url }} + + + Redirecting to {{ url }}. + + diff --git a/tests/FileLoaderTest.php b/tests/FileLoaderTest.php index 7cfa4e6..c31147d 100644 --- a/tests/FileLoaderTest.php +++ b/tests/FileLoaderTest.php @@ -10,6 +10,7 @@ use Madapaja\TwigModule\Resource\Page\Index; use Madapaja\TwigModule\Resource\Page\NoTemplate; use Madapaja\TwigModule\Resource\Page\Page; +use Madapaja\TwigModule\Resource\Page\Redirect; use PHPUnit_Framework_TestCase; use Ray\Di\Injector; @@ -122,4 +123,25 @@ public function testIndexTemplateWithoutPaths() $ro->onGet(); $this->assertSame('Hello, BEAR.Sunday!', \trim((string) $ro)); } + + public function testNoRedirectOnGet() + { + $injector = $this->getInjector(); + $ro = $injector->getInstance(Redirect::class); + $ro->onGet(); + + $this->assertSame(Code::OK, $ro->code); + $this->assertSame('foo is bar.', \trim((string) $ro)); + } + + public function testRedirectOnPost() + { + $injector = $this->getInjector(); + $ro = $injector->getInstance(Redirect::class); + $ro->onPost(); + + $this->assertSame(Code::FOUND, $ro->code); + $this->assertSame('/path/to/baz', $ro->headers['Location']); + $this->assertRegexp('#^.*Redirecting to /path/to/baz.*$#s', \trim((string) $ro)); + } } diff --git a/var/templates/redirect/redirect.html.twig b/var/templates/redirect/redirect.html.twig new file mode 100644 index 0000000..da82d89 --- /dev/null +++ b/var/templates/redirect/redirect.html.twig @@ -0,0 +1,11 @@ + + + + + + Redirecting to {{ url }} + + + Redirecting to {{ url }}. + +