From 86e5ac6cc48662e54e69c7a1b90c4294580478f3 Mon Sep 17 00:00:00 2001 From: Ambroise Maupate Date: Fri, 4 Aug 2023 16:29:27 +0200 Subject: [PATCH] feat(TreeWalker): Added new tag `roadiz_core.tree_walker_definition_factory` to inject TreeWalker definitions into TreeWalkerGenerator and any BlocksAwareWebResponseOutputDataTransformerTrait --- ...eWebResponseOutputDataTransformerTrait.php | 10 ++- .../WebResponseOutputDataTransformer.php | 15 +++- .../DefinitionFactoryConfiguration.php | 27 +++++++ .../Definition/DefinitionFactoryInterface.php | 12 +++ .../Api/TreeWalker/TreeWalkerGenerator.php | 74 +++++++++++++++++-- ...reeWalkerDefinitionFactoryCompilerPass.php | 43 +++++++++++ lib/RoadizCoreBundle/src/RoadizCoreBundle.php | 2 + 7 files changed, 173 insertions(+), 10 deletions(-) create mode 100644 lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryConfiguration.php create mode 100644 lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryInterface.php create mode 100644 lib/RoadizCoreBundle/src/DependencyInjection/Compiler/TreeWalkerDefinitionFactoryCompilerPass.php diff --git a/lib/RoadizCoreBundle/src/Api/DataTransformer/BlocksAwareWebResponseOutputDataTransformerTrait.php b/lib/RoadizCoreBundle/src/Api/DataTransformer/BlocksAwareWebResponseOutputDataTransformerTrait.php index e766709c..2e89b12e 100644 --- a/lib/RoadizCoreBundle/src/Api/DataTransformer/BlocksAwareWebResponseOutputDataTransformerTrait.php +++ b/lib/RoadizCoreBundle/src/Api/DataTransformer/BlocksAwareWebResponseOutputDataTransformerTrait.php @@ -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; @@ -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; /** @@ -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 $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; diff --git a/lib/RoadizCoreBundle/src/Api/DataTransformer/WebResponseOutputDataTransformer.php b/lib/RoadizCoreBundle/src/Api/DataTransformer/WebResponseOutputDataTransformer.php index 950eeef1..a91c4b04 100644 --- a/lib/RoadizCoreBundle/src/Api/DataTransformer/WebResponseOutputDataTransformer.php +++ b/lib/RoadizCoreBundle/src/Api/DataTransformer/WebResponseOutputDataTransformer.php @@ -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; @@ -29,6 +31,7 @@ class WebResponseOutputDataTransformer implements WebResponseDataTransformerInte private CacheItemPoolInterface $cacheItemPool; private UrlGeneratorInterface $urlGenerator; private RealmResolverInterface $realmResolver; + private TreeWalkerGenerator $treeWalkerGenerator; public function __construct( NodesSourcesHeadFactoryInterface $nodesSourcesHeadFactory, @@ -36,7 +39,8 @@ public function __construct( WalkerContextInterface $walkerContext, CacheItemPoolInterface $cacheItemPool, UrlGeneratorInterface $urlGenerator, - RealmResolverInterface $realmResolver + RealmResolverInterface $realmResolver, + TreeWalkerGenerator $treeWalkerGenerator ) { $this->nodesSourcesHeadFactory = $nodesSourcesHeadFactory; $this->breadcrumbsFactory = $breadcrumbsFactory; @@ -44,6 +48,7 @@ public function __construct( $this->cacheItemPool = $cacheItemPool; $this->urlGenerator = $urlGenerator; $this->realmResolver = $realmResolver; + $this->treeWalkerGenerator = $treeWalkerGenerator; } protected function getWalkerContext(): WalkerContextInterface @@ -61,6 +66,14 @@ protected function getChildrenNodeSourceWalkerMaxLevel(): int return 5; } + public function getTreeWalkerGenerator(): TreeWalkerGenerator + { + return $this->treeWalkerGenerator; + } + + /** + * @return class-string + */ protected function getChildrenNodeSourceWalkerClassname(): string { return AutoChildrenNodeSourceWalker::class; diff --git a/lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryConfiguration.php b/lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryConfiguration.php new file mode 100644 index 00000000..a63ca9c1 --- /dev/null +++ b/lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryConfiguration.php @@ -0,0 +1,27 @@ +classname = $classname; + $this->onlyVisible = $onlyVisible; + $this->definitionFactory = $definitionFactory; + } +} diff --git a/lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryInterface.php b/lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryInterface.php new file mode 100644 index 00000000..85e75536 --- /dev/null +++ b/lib/RoadizCoreBundle/src/Api/TreeWalker/Definition/DefinitionFactoryInterface.php @@ -0,0 +1,12 @@ + + */ + private array $walkerDefinitionFactories = []; + public function __construct( NodeSourceApi $nodeSourceApi, NodeTypes $nodeTypesBag, @@ -34,7 +42,7 @@ public function __construct( /** * @param string $nodeType - * @param class-string $walkerClass + * @param class-string $walkerClass * @param TranslationInterface $translation * @param int $maxLevel * @return array @@ -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 @@ -72,4 +78,62 @@ public function getTreeWalkersForTypeAtRoot( return $walkers; } + + /** + * @param object $root + * @param class-string $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 + ); + } } diff --git a/lib/RoadizCoreBundle/src/DependencyInjection/Compiler/TreeWalkerDefinitionFactoryCompilerPass.php b/lib/RoadizCoreBundle/src/DependencyInjection/Compiler/TreeWalkerDefinitionFactoryCompilerPass.php new file mode 100644 index 00000000..b8c0d188 --- /dev/null +++ b/lib/RoadizCoreBundle/src/DependencyInjection/Compiler/TreeWalkerDefinitionFactoryCompilerPass.php @@ -0,0 +1,43 @@ +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 + ] + ); + } + } + } + } + } +} diff --git a/lib/RoadizCoreBundle/src/RoadizCoreBundle.php b/lib/RoadizCoreBundle/src/RoadizCoreBundle.php index 540b3975..a37d6c1c 100644 --- a/lib/RoadizCoreBundle/src/RoadizCoreBundle.php +++ b/lib/RoadizCoreBundle/src/RoadizCoreBundle.php @@ -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; @@ -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()); } }