Skip to content

Commit

Permalink
feat(TreeWalker): Added new tag `roadiz_core.tree_walker_definition_f…
Browse files Browse the repository at this point in the history
…actory` to inject TreeWalker definitions into TreeWalkerGenerator and any BlocksAwareWebResponseOutputDataTransformerTrait
  • Loading branch information
ambroisemaupate committed Aug 4, 2023
1 parent ddc9ec7 commit 86e5ac6
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use RZ\Roadiz\CoreBundle\Api\Model\BlocksAwareWebResponseInterface;
use RZ\Roadiz\CoreBundle\Api\Model\RealmsAwareWebResponseInterface;
use RZ\Roadiz\CoreBundle\Api\Model\WebResponseInterface;
use RZ\Roadiz\CoreBundle\Api\TreeWalker\TreeWalkerGenerator;
use RZ\Roadiz\CoreBundle\Entity\NodesSources;
use RZ\TreeWalker\AbstractWalker;
use RZ\TreeWalker\WalkerContextInterface;
Expand All @@ -16,6 +17,7 @@ trait BlocksAwareWebResponseOutputDataTransformerTrait
{
abstract protected function getWalkerContext(): WalkerContextInterface;
abstract protected function getCacheItemPool(): CacheItemPoolInterface;
abstract protected function getTreeWalkerGenerator(): TreeWalkerGenerator;
abstract protected function getChildrenNodeSourceWalkerMaxLevel(): int;

/**
Expand All @@ -26,14 +28,14 @@ abstract protected function getChildrenNodeSourceWalkerClassname(): string;
protected function injectBlocks(BlocksAwareWebResponseInterface $output, NodesSources $data): WebResponseInterface
{
if (!$output instanceof RealmsAwareWebResponseInterface || !$output->isHidingBlocks()) {
/** @var class-string<AbstractWalker> $childrenNodeSourceWalkerClassname */
$childrenNodeSourceWalkerClassname = $this->getChildrenNodeSourceWalkerClassname();
$output->setBlocks($childrenNodeSourceWalkerClassname::build(
$walker = $this->getTreeWalkerGenerator()->buildForRoot(
$data,
$this->getChildrenNodeSourceWalkerClassname(),
$this->getWalkerContext(),
$this->getChildrenNodeSourceWalkerMaxLevel(),
$this->getCacheItemPool()
)->getChildren());
);
$output->setBlocks($walker->getChildren());
}

return $output;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
use RZ\Roadiz\CoreBundle\Api\Model\WebResponse;
use RZ\Roadiz\CoreBundle\Api\Model\WebResponseInterface;
use RZ\Roadiz\CoreBundle\Api\TreeWalker\AutoChildrenNodeSourceWalker;
use RZ\Roadiz\CoreBundle\Api\TreeWalker\TreeWalkerGenerator;
use RZ\Roadiz\CoreBundle\Entity\NodesSources;
use RZ\Roadiz\CoreBundle\Realm\RealmResolverInterface;
use RZ\TreeWalker\AbstractWalker;
use RZ\TreeWalker\WalkerContextInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
Expand All @@ -29,21 +31,24 @@ class WebResponseOutputDataTransformer implements WebResponseDataTransformerInte
private CacheItemPoolInterface $cacheItemPool;
private UrlGeneratorInterface $urlGenerator;
private RealmResolverInterface $realmResolver;
private TreeWalkerGenerator $treeWalkerGenerator;

public function __construct(
NodesSourcesHeadFactoryInterface $nodesSourcesHeadFactory,
BreadcrumbsFactoryInterface $breadcrumbsFactory,
WalkerContextInterface $walkerContext,
CacheItemPoolInterface $cacheItemPool,
UrlGeneratorInterface $urlGenerator,
RealmResolverInterface $realmResolver
RealmResolverInterface $realmResolver,
TreeWalkerGenerator $treeWalkerGenerator
) {
$this->nodesSourcesHeadFactory = $nodesSourcesHeadFactory;
$this->breadcrumbsFactory = $breadcrumbsFactory;
$this->walkerContext = $walkerContext;
$this->cacheItemPool = $cacheItemPool;
$this->urlGenerator = $urlGenerator;
$this->realmResolver = $realmResolver;
$this->treeWalkerGenerator = $treeWalkerGenerator;
}

protected function getWalkerContext(): WalkerContextInterface
Expand All @@ -61,6 +66,14 @@ protected function getChildrenNodeSourceWalkerMaxLevel(): int
return 5;
}

public function getTreeWalkerGenerator(): TreeWalkerGenerator
{
return $this->treeWalkerGenerator;
}

/**
* @return class-string<AbstractWalker>
*/
protected function getChildrenNodeSourceWalkerClassname(): string
{
return AutoChildrenNodeSourceWalker::class;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\Api\TreeWalker\Definition;

final class DefinitionFactoryConfiguration
{
/**
* @var class-string
*/
public string $classname;
public bool $onlyVisible;
public DefinitionFactoryInterface $definitionFactory;

/**
* @param class-string $classname
* @param DefinitionFactoryInterface $definitionFactory
* @param bool $onlyVisible
*/
public function __construct(string $classname, DefinitionFactoryInterface $definitionFactory, bool $onlyVisible)
{
$this->classname = $classname;
$this->onlyVisible = $onlyVisible;
$this->definitionFactory = $definitionFactory;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\Api\TreeWalker\Definition;

use RZ\TreeWalker\WalkerContextInterface;

interface DefinitionFactoryInterface
{
public function create(WalkerContextInterface $context, bool $onlyVisible = true): callable;
}
74 changes: 69 additions & 5 deletions lib/RoadizCoreBundle/src/Api/TreeWalker/TreeWalkerGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@

use Psr\Cache\CacheItemPoolInterface;
use RZ\Roadiz\Core\AbstractEntities\TranslationInterface;
use RZ\Roadiz\CoreBundle\Api\TreeWalker\Definition\DefinitionFactoryConfiguration;
use RZ\Roadiz\CoreBundle\Api\TreeWalker\Definition\DefinitionFactoryInterface;
use RZ\Roadiz\CoreBundle\Bag\NodeTypes;
use RZ\Roadiz\CoreBundle\Entity\NodesSources;
use RZ\Roadiz\CoreBundle\EntityApi\NodeSourceApi;
use RZ\TreeWalker\AbstractWalker;
use RZ\TreeWalker\WalkerContextInterface;
use RZ\TreeWalker\WalkerInterface;
use Symfony\Component\String\UnicodeString;
Expand All @@ -20,6 +23,11 @@ final class TreeWalkerGenerator
private WalkerContextInterface $walkerContext;
private CacheItemPoolInterface $cacheItemPool;

/**
* @var array<class-string, DefinitionFactoryConfiguration>
*/
private array $walkerDefinitionFactories = [];

public function __construct(
NodeSourceApi $nodeSourceApi,
NodeTypes $nodeTypesBag,
Expand All @@ -34,7 +42,7 @@ public function __construct(

/**
* @param string $nodeType
* @param class-string $walkerClass
* @param class-string<AbstractWalker> $walkerClass
* @param TranslationInterface $translation
* @param int $maxLevel
* @return array<string, WalkerInterface>
Expand All @@ -59,11 +67,9 @@ public function getTreeWalkersForTypeAtRoot(
->camel()
->toString();

/** @var callable $callable */
$callable = [$walkerClass, 'build'];
$walkers[$walkerName] = call_user_func(
$callable,
$walkers[$walkerName] = $this->buildForRoot(
$root,
$walkerClass,
$this->walkerContext,
$maxLevel,
$this->cacheItemPool
Expand All @@ -72,4 +78,62 @@ public function getTreeWalkersForTypeAtRoot(

return $walkers;
}

/**
* @param object $root
* @param class-string<AbstractWalker> $walkerClass
* @param WalkerContextInterface $walkerContext
* @param int $maxLevel
* @param CacheItemPoolInterface $cacheItemPool
* @return WalkerInterface
*/
public function buildForRoot(
object $root,
string $walkerClass,
WalkerContextInterface $walkerContext,
int $maxLevel,
CacheItemPoolInterface $cacheItemPool
): WalkerInterface {
/** @var callable $callable */
$callable = [$walkerClass, 'build'];
$walker = call_user_func(
$callable,
$root,
$walkerContext,
$maxLevel,
$cacheItemPool
);

foreach ($this->walkerDefinitionFactories as $definitionFactoryConfiguration) {
$walker->addDefinition(
$definitionFactoryConfiguration->classname,
$definitionFactoryConfiguration->definitionFactory->create(
$this->walkerContext,
$definitionFactoryConfiguration->onlyVisible
)
);
}
return $walker;
}

/**
* Inject definition from factories registered in the container
* using `roadiz_core.tree_walker_definition_factory` tag.
*
* @param class-string $classname
* @param DefinitionFactoryInterface $definitionFactory
* @param bool $onlyVisible
* @return void
*/
public function addDefinitionFactoryConfiguration(
string $classname,
DefinitionFactoryInterface $definitionFactory,
bool $onlyVisible
): void {
$this->walkerDefinitionFactories[$classname] = new DefinitionFactoryConfiguration(
$classname,
$definitionFactory,
$onlyVisible
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\CoreBundle\DependencyInjection\Compiler;

use RZ\Roadiz\CoreBundle\Api\TreeWalker\TreeWalkerGenerator;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class TreeWalkerDefinitionFactoryCompilerPass implements CompilerPassInterface
{
/**
* @inheritDoc
*/
public function process(ContainerBuilder $container): void
{
if ($container->has(TreeWalkerGenerator::class)) {
$definition = $container->findDefinition(TreeWalkerGenerator::class);
$serviceIds = $container->findTaggedServiceIds(
'roadiz_core.tree_walker_definition_factory',
);
foreach ($serviceIds as $serviceId => $tags) {
foreach ($tags as $tag) {
if (isset($tag['classname']) && \is_string($tag['classname'])) {
/*
* TreeWalkerGenerator::addDefinitionFactoryConfiguration($classname, $serviceId, $onlyVisible = true)
*/
$definition->addMethodCall(
'addDefinitionFactoryConfiguration',
[
$tag['classname'],
new Reference($serviceId),
$tag['onlyVisible'] ?? true
]
);
}
}
}
}
}
}
2 changes: 2 additions & 0 deletions lib/RoadizCoreBundle/src/RoadizCoreBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use RZ\Roadiz\CoreBundle\DependencyInjection\Compiler\NodeWorkflowCompilerPass;
use RZ\Roadiz\CoreBundle\DependencyInjection\Compiler\PathResolverCompilerPass;
use RZ\Roadiz\CoreBundle\DependencyInjection\Compiler\RateLimitersCompilerPass;
use RZ\Roadiz\CoreBundle\DependencyInjection\Compiler\TreeWalkerDefinitionFactoryCompilerPass;
use RZ\Roadiz\CoreBundle\DependencyInjection\Compiler\TwigLoaderCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;
Expand All @@ -40,5 +41,6 @@ public function build(ContainerBuilder $container): void
$container->addCompilerPass(new PathResolverCompilerPass());
$container->addCompilerPass(new FlysystemStorageCompilerPass());
$container->addCompilerPass(new TwigLoaderCompilerPass());
$container->addCompilerPass(new TreeWalkerDefinitionFactoryCompilerPass());
}
}

0 comments on commit 86e5ac6

Please sign in to comment.