From b0c1cb1f9f6fa6c980b912a9a108dbf971392d54 Mon Sep 17 00:00:00 2001 From: Andreas Schempp Date: Fri, 24 Jul 2020 09:43:29 +0200 Subject: [PATCH] Rewrite the page annotation to follow the Route annotation (see #1973) Description ----------- | Q | A | -----------------| --- | Fixed issues | Fixes https://github.com/contao/contao/pull/1971 This is mostly about allowing a string for methods, same as Symfony does. There are two use cases: ```php // Custom page controller /** * @Page(methods="GET") */ class MyPageController { } ``` ```yaml // services.yml services: App\Controller\Page\MyPageController: tags: - { name: 'contao.page', methods: 'GET' } ``` Commits ------- 1508e96d Rewrite the page annotation to follow the Route annotation 7cc0debe Fixed type information fc3d9a84 CS d4b1ab47 CS 526ae580 Merge branch '4.10' into bugfix/route-config 519f9f1d CS --- core-bundle/src/Routing/Page/PageRegistry.php | 1 + core-bundle/src/Routing/Page/PageRoute.php | 5 +- core-bundle/src/Routing/Page/RouteConfig.php | 9 +- core-bundle/src/ServiceAnnotation/Page.php | 182 ++++++++++++++++-- 4 files changed, 174 insertions(+), 23 deletions(-) diff --git a/core-bundle/src/Routing/Page/PageRegistry.php b/core-bundle/src/Routing/Page/PageRegistry.php index ca4a5e19ca8..8e8c6e7e3db 100644 --- a/core-bundle/src/Routing/Page/PageRegistry.php +++ b/core-bundle/src/Routing/Page/PageRegistry.php @@ -62,6 +62,7 @@ public function getPathRegex(): array { $prefixes = []; + /** @var RouteConfig $config */ foreach ($this->routeConfigs as $type => $config) { $regex = $config->getPathRegex(); diff --git a/core-bundle/src/Routing/Page/PageRoute.php b/core-bundle/src/Routing/Page/PageRoute.php index c8fbe1198f3..31325f8e888 100644 --- a/core-bundle/src/Routing/Page/PageRoute.php +++ b/core-bundle/src/Routing/Page/PageRoute.php @@ -43,7 +43,10 @@ class PageRoute extends Route */ private $content; - public function __construct(PageModel $pageModel, string $path = '', array $defaults = [], array $requirements = [], array $options = [], array $methods = []) + /** + * @param string|array $methods + */ + public function __construct(PageModel $pageModel, string $path = '', array $defaults = [], array $requirements = [], array $options = [], $methods = []) { $pageModel->loadDetails(); diff --git a/core-bundle/src/Routing/Page/RouteConfig.php b/core-bundle/src/Routing/Page/RouteConfig.php index 7c348614f36..95e38e64e25 100644 --- a/core-bundle/src/Routing/Page/RouteConfig.php +++ b/core-bundle/src/Routing/Page/RouteConfig.php @@ -45,11 +45,14 @@ final class RouteConfig private $defaults; /** - * @var array + * @var array */ private $methods; - public function __construct(string $path = null, string $pathRegex = null, string $urlSuffix = null, array $requirements = [], array $options = [], array $defaults = [], array $methods = []) + /** + * @param string|array $methods + */ + public function __construct(string $path = null, string $pathRegex = null, string $urlSuffix = null, array $requirements = [], array $options = [], array $defaults = [], $methods = []) { $this->path = $path; $this->pathRegex = $pathRegex; @@ -57,7 +60,7 @@ public function __construct(string $path = null, string $pathRegex = null, strin $this->requirements = $requirements; $this->options = $options; $this->defaults = $defaults; - $this->methods = $methods; + $this->methods = \is_array($methods) ? $methods : [$methods]; } public function getPath(): ?string diff --git a/core-bundle/src/ServiceAnnotation/Page.php b/core-bundle/src/ServiceAnnotation/Page.php index b34e38640f0..262451496e5 100644 --- a/core-bundle/src/ServiceAnnotation/Page.php +++ b/core-bundle/src/ServiceAnnotation/Page.php @@ -12,8 +12,6 @@ namespace Contao\CoreBundle\ServiceAnnotation; -use Doctrine\Common\Annotations\Annotation\Attribute; -use Doctrine\Common\Annotations\Annotation\Attributes; use Doctrine\Common\Annotations\Annotation\Target; use Terminal42\ServiceAnnotationBundle\ServiceAnnotationInterface; @@ -22,32 +20,86 @@ * * @Annotation * @Target({"CLASS", "METHOD"}) - * @Attributes({ - * @Attribute("value", type = "string"), - * @Attribute("path", type = "string"), - * @Attribute("urlSuffix", type = "string"), - * @Attribute("requirements", type = "array"), - * @Attribute("options", type = "array"), - * @Attribute("defaults", type = "array"), - * @Attribute("methods", type = "array"), - * @Attribute("contentComposition", type = "boolean"), - * }) + * + * @see \Symfony\Component\Routing\Annotation\Route */ final class Page implements ServiceAnnotationInterface { + /** + * @var string + */ + private $type; + + /** + * @var bool + */ + private $contentComposition = true; + + /** + * @var string|null + */ + private $path; + + /** + * @var string|null + */ + private $urlSuffix; + + /** + * @var array + */ + private $requirements = []; + /** * @var array */ - private $attributes; + private $options = []; - public function __construct(array $attributes) + /** + * @var array + */ + private $defaults = []; + + /** + * @var array + */ + private $methods = []; + + public function __construct(array $data) { - if (isset($attributes['value'])) { - $attributes['type'] = $attributes['value']; - unset($attributes['value']); + if (isset($data['value'])) { + $data['type'] = $data['value']; + unset($data['value']); + } + + if (!isset($data['type'])) { + throw new \LogicException('@Page annotation requires a type property.'); + } + + if (isset($data['locale'])) { + $data['defaults']['_locale'] = $data['locale']; + unset($data['locale']); + } + + if (isset($data['format'])) { + $data['defaults']['_format'] = $data['format']; + unset($data['format']); + } + + if (isset($data['utf8'])) { + $data['options']['utf8'] = filter_var($data['utf8'], FILTER_VALIDATE_BOOLEAN) ?: false; + unset($data['utf8']); } - $this->attributes = $attributes; + foreach ($data as $key => $value) { + $method = 'set'.str_replace('_', '', $key); + + if (!method_exists($this, $method)) { + throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, static::class)); + } + + $this->$method($value); + } } public function getName(): string @@ -57,6 +109,98 @@ public function getName(): string public function getAttributes(): array { - return $this->attributes; + return [ + 'type' => $this->type, + 'contentComposition' => $this->contentComposition, + 'path' => $this->path, + 'urlSuffix' => $this->urlSuffix, + 'requirements' => $this->requirements, + 'options' => $this->options, + 'defaults' => $this->defaults, + 'methods' => $this->methods, + ]; + } + + public function getType(): string + { + return $this->type; + } + + public function setType(string $type): void + { + $this->type = $type; + } + + public function getContentComposition(): bool + { + return $this->contentComposition; + } + + public function setContentComposition(bool $contentComposition): void + { + $this->contentComposition = $contentComposition; + } + + public function setPath(?string $path): void + { + $this->path = $path; + } + + public function getPath(): ?string + { + return $this->path; + } + + public function getUrlSuffix(): ?string + { + return $this->urlSuffix; + } + + public function setUrlSuffix(string $urlSuffix): void + { + $this->urlSuffix = $urlSuffix; + } + + public function setRequirements(array $requirements): void + { + $this->requirements = $requirements; + } + + public function getRequirements(): array + { + return $this->requirements; + } + + public function setOptions(array $options): void + { + $this->options = $options; + } + + public function getOptions(): array + { + return $this->options; + } + + public function setDefaults(array $defaults): void + { + $this->defaults = $defaults; + } + + public function getDefaults(): array + { + return $this->defaults; + } + + /** + * @param string|array $methods + */ + public function setMethods($methods): void + { + $this->methods = \is_array($methods) ? $methods : [$methods]; + } + + public function getMethods(): array + { + return $this->methods; } }