Skip to content
4 changes: 4 additions & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
50 changes: 50 additions & 0 deletions src/Configuration/Content/TaxonomyType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Bolt\Configuration\Content;

use Bolt\Collection\DeepCollection;
use Tightenco\Collect\Support\Collection;

class TaxonomyType extends DeepCollection
{
public function __call($name, $arguments)
{
return $this->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,
// when it is created on the fly
'virtual' => true,
]);
}

public function getSlug(): string
{
return $this->get('slug');
}
}
51 changes: 50 additions & 1 deletion src/Entity/Taxonomy.php
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -50,16 +52,32 @@ 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
{
return $this->id;
}

/**
* @see \Bolt\Event\Listener\TaxonomyFillListener
*/
public function setDefinitionFromTaxonomyTypesConfig(LaravelCollection $taxonomyTypesConfig): void
{
$this->taxonomyTypeDefinition = TaxonomyType::factory($this->type, $taxonomyTypesConfig);
}

/**
* @return Collection|Content[]
*/
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
}
34 changes: 34 additions & 0 deletions src/Event/Listener/TaxonomyFillListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Bolt\Event\Listener;

use Bolt\Configuration\Config;
use Bolt\Entity\Taxonomy;
use Doctrine\ORM\Event\LifecycleEventArgs;

class TaxonomyFillListener
{
/** @var Config */
private $config;

public function __construct(Config $config)
{
$this->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'));
}
}
2 changes: 1 addition & 1 deletion src/Twig/ContentExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Twig/TextExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ 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]);
}
}
Expand Down