From 04aa4a06b51dec503735b60b3be617e61bdd76cb Mon Sep 17 00:00:00 2001 From: Ivo Valchev Date: Fri, 23 Oct 2020 14:53:06 +0200 Subject: [PATCH 1/7] Fix PHPStan breaking on `url_decode` --- src/Twig/TextExtension.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Twig/TextExtension.php b/src/Twig/TextExtension.php index 1dbd57afb..a80e142b1 100644 --- a/src/Twig/TextExtension.php +++ b/src/Twig/TextExtension.php @@ -98,6 +98,7 @@ public function urlDecode(string $string) $param = explode('=', $chunk); if ($param) { + if (! empty($param)) { $params[urldecode($param[0])] = urldecode($param[1]); } } From f9e9797b86505a3de1856a237f127e460e26b152 Mon Sep 17 00:00:00 2001 From: Ivo Valchev Date: Fri, 23 Oct 2020 14:57:23 +0200 Subject: [PATCH 2/7] commit deleted line too --- src/Twig/TextExtension.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Twig/TextExtension.php b/src/Twig/TextExtension.php index a80e142b1..1f2df8389 100644 --- a/src/Twig/TextExtension.php +++ b/src/Twig/TextExtension.php @@ -97,7 +97,6 @@ public function urlDecode(string $string) foreach (explode('&', $string) as $chunk) { $param = explode('=', $chunk); - if ($param) { if (! empty($param)) { $params[urldecode($param[0])] = urldecode($param[1]); } From b1ebedc6b5a0b5b3e4e4bab4cec3e876232ef8e6 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Fri, 23 Oct 2020 14:55:25 +0100 Subject: [PATCH 3/7] Taxonomies now store a "taxonomy type definition" in the same way as content types store a "content type definition". This allows the use of the singular_slug directive when generating a URL. --- config/services.yaml | 4 ++ src/Configuration/Content/TaxonomyType.php | 50 ++++++++++++++++++++ src/Entity/Taxonomy.php | 51 ++++++++++++++++++++- src/Event/Listener/TaxonomyFillListener.php | 33 +++++++++++++ src/Twig/ContentExtension.php | 2 +- 5 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 src/Configuration/Content/TaxonomyType.php create mode 100644 src/Event/Listener/TaxonomyFillListener.php diff --git a/config/services.yaml b/config/services.yaml index 8390dfb10..cfe7636d1 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -60,6 +60,10 @@ services: tags: - { name: doctrine.event_listener, event: loadClassMetadata } + Bolt\Event\Listener\TaxonomyFillListener: + tags: + - { name: doctrine.event_listener, event: postLoad } + Bolt\Extension\RoutesLoader: tags: [routing.loader] diff --git a/src/Configuration/Content/TaxonomyType.php b/src/Configuration/Content/TaxonomyType.php new file mode 100644 index 000000000..4aee831df --- /dev/null +++ b/src/Configuration/Content/TaxonomyType.php @@ -0,0 +1,50 @@ +get($name); + } + + public static function factory(?string $name, Collection $taxonomyTypesConfig): self + { + if ($taxonomyTypesConfig->has($name)) { + return new self($taxonomyTypesConfig->get($name)); + } + + $taxonomyType = $taxonomyTypesConfig + ->filter(function (Collection $taxonomyTypeConfig) use ($name): bool { + return $taxonomyTypeConfig['singular_slug'] === $name; + }) + ->map(function (Collection $taxonomyTypeConfig): self { + return new self($taxonomyTypeConfig); + }) + ->first(); + + if ($taxonomyType) { + return $taxonomyType; + } + + return new self([ + 'name' => $name, + 'slug' => $name, + 'singular_slug' => $name, + 'singular_name' => $name, + 'locales' => [], + 'fields' => new Collection(), + // when it is created on the fly + 'virtual' => true, + ]); + } + + public function getSlug(): string + { + return $this->get('slug'); + } +} \ No newline at end of file diff --git a/src/Entity/Taxonomy.php b/src/Entity/Taxonomy.php index 90a677c00..1467f900a 100644 --- a/src/Entity/Taxonomy.php +++ b/src/Entity/Taxonomy.php @@ -5,10 +5,12 @@ namespace Bolt\Entity; use Bolt\Common\Str; +use Bolt\Configuration\Content\TaxonomyType; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; +use Tightenco\Collect\Support\Collection as LaravelCollection; /** * @ORM\Entity(repositoryClass="Bolt\Repository\TaxonomyRepository") @@ -50,9 +52,17 @@ class Taxonomy */ private $sortorder = 0; - public function __construct() + /** @var TaxonomyType|null */ + private $taxonomyTypeDefinition = null; + + public function __construct(?TaxonomyType $taxonomyTypeDefinition = null) { $this->content = new ArrayCollection(); + + if ($taxonomyTypeDefinition) { + $this->setType($taxonomyTypeDefinition->getSlug()); + $this->setDefinition($taxonomyTypeDefinition); + } } public function getId(): ?int @@ -60,6 +70,14 @@ public function getId(): ?int return $this->id; } + /** + * @see \Bolt\Event\Listener\TaxonomyFillListener + */ + public function setDefinitionFromTaxonomyTypesConfig(LaravelCollection $taxonomyTypesConfig): void + { + $this->taxonomyTypeDefinition = TaxonomyType::factory($this->type, $taxonomyTypesConfig); + } + /** * @return Collection|Content[] */ @@ -86,6 +104,24 @@ public function removeContent(Content $content): self return $this; } + public function getTaxonomyTypeSlug(): string + { + if ($this->getDefinition() === null) { + throw new \RuntimeException('Taxonomy not fully initialized'); + } + + return $this->getDefinition()->get('slug'); + } + + public function getTaxonomyTypeSingularSlug(): string + { + if ($this->getDefinition() === null) { + throw new \RuntimeException('Taxonomy not fully initialized'); + } + + return $this->getDefinition()->get('singular_slug'); + } + public function getType(): ?string { return $this->type; @@ -133,4 +169,17 @@ public function setSortorder(int $sortorder): self return $this; } + + public function setDefinition(TaxonomyType $taxonomyType): void + { + $this->taxonomyTypeDefinition = $taxonomyType; + } + + /** + * @Groups("get_definition") + */ + public function getDefinition(): ?TaxonomyType + { + return $this->taxonomyTypeDefinition; + } } diff --git a/src/Event/Listener/TaxonomyFillListener.php b/src/Event/Listener/TaxonomyFillListener.php new file mode 100644 index 000000000..5a62e5f85 --- /dev/null +++ b/src/Event/Listener/TaxonomyFillListener.php @@ -0,0 +1,33 @@ +config = $config; + } + + public function postLoad(LifecycleEventArgs $args): void + { + $entity = $args->getEntity(); + + if ($entity instanceof Taxonomy) { + $this->fillTaxonomy($entity); + } + } + + public function fillTaxonomy(Taxonomy $entity): void + { + $entity->setDefinitionFromTaxonomyTypesConfig($this->config->get('taxonomies')); + } +} \ No newline at end of file diff --git a/src/Twig/ContentExtension.php b/src/Twig/ContentExtension.php index 5be1c0028..43f366bba 100644 --- a/src/Twig/ContentExtension.php +++ b/src/Twig/ContentExtension.php @@ -384,7 +384,7 @@ public function getLink($contentOrTaxonomy, bool $canonical = false, ?string $lo if ($contentOrTaxonomy instanceof Taxonomy) { return $this->urlGenerator->generate('taxonomy', [ - 'taxonomyslug' => $contentOrTaxonomy->getType(), + 'taxonomyslug' => $contentOrTaxonomy->getTaxonomyTypeSingularSlug(), 'slug' => $contentOrTaxonomy->getSlug(), ]); } From 396ee9602d5d4079295501d4f16b103e2ae9339b Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Fri, 23 Oct 2020 15:07:35 +0100 Subject: [PATCH 4/7] Removed content-specific keys from a generated TaxonomyType --- src/Configuration/Content/TaxonomyType.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Configuration/Content/TaxonomyType.php b/src/Configuration/Content/TaxonomyType.php index 4aee831df..a32e4d85f 100644 --- a/src/Configuration/Content/TaxonomyType.php +++ b/src/Configuration/Content/TaxonomyType.php @@ -36,8 +36,6 @@ public static function factory(?string $name, Collection $taxonomyTypesConfig): 'slug' => $name, 'singular_slug' => $name, 'singular_name' => $name, - 'locales' => [], - 'fields' => new Collection(), // when it is created on the fly 'virtual' => true, ]); From 02f027a46848620031613c243f5b576ba9157762 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Fri, 23 Oct 2020 17:55:21 +0100 Subject: [PATCH 5/7] Corrected TaxonomyFillListener for coding style, removed unnecessary using --- src/Event/Listener/TaxonomyFillListener.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Event/Listener/TaxonomyFillListener.php b/src/Event/Listener/TaxonomyFillListener.php index 5a62e5f85..4d8b07aad 100644 --- a/src/Event/Listener/TaxonomyFillListener.php +++ b/src/Event/Listener/TaxonomyFillListener.php @@ -1,9 +1,10 @@ setDefinitionFromTaxonomyTypesConfig($this->config->get('taxonomies')); } -} \ No newline at end of file +} From de2b91b774985274ca3066867dee5c3e27c8d368 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Fri, 23 Oct 2020 17:58:45 +0100 Subject: [PATCH 6/7] Added new line to TaxonomyType --- src/Configuration/Content/TaxonomyType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Configuration/Content/TaxonomyType.php b/src/Configuration/Content/TaxonomyType.php index a32e4d85f..0eb6f236d 100644 --- a/src/Configuration/Content/TaxonomyType.php +++ b/src/Configuration/Content/TaxonomyType.php @@ -45,4 +45,4 @@ public function getSlug(): string { return $this->get('slug'); } -} \ No newline at end of file +} From d17bcea1e613f7ca558b32a2ffe83644373541f8 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Fri, 23 Oct 2020 18:05:40 +0100 Subject: [PATCH 7/7] Added strict types to TaxonomyType --- src/Configuration/Content/TaxonomyType.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Configuration/Content/TaxonomyType.php b/src/Configuration/Content/TaxonomyType.php index 0eb6f236d..54cfba798 100644 --- a/src/Configuration/Content/TaxonomyType.php +++ b/src/Configuration/Content/TaxonomyType.php @@ -1,5 +1,7 @@