Skip to content

Commit 155defa

Browse files
committed
Sorts twig namespaces to manage templates priority
1 parent 4aa3f3b commit 155defa

4 files changed

Lines changed: 75 additions & 2 deletions

File tree

config/services/services.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,4 @@ services:
149149
Softspring\CmsBundle\Routing\Loader\RoutingLoader:
150150
arguments:
151151
$routingProviders: !tagged_iterator { tag: sfs_cms.routing_provider }
152-
tags: [ 'routing.loader' ]
152+
tags: [ 'routing.loader' ]

src/DependencyInjection/Compiler/AddTwigBundlesNamespacesPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public function process(ContainerBuilder $container): void
1818

1919
// register project namespaces before collections to allow overriding
2020
foreach ((new Finder())->in(trim($this->templatesPath).'/bundles')->depth(0)->directories() as $directory) {
21-
$twigFilesystemLoaderDefinition->addMethodCall('prependPath', [$directory->getRealPath(), str_replace('Bundle', '', $directory->getBasename())]);
21+
$twigFilesystemLoaderDefinition->addMethodCall('addPath', [$directory->getRealPath(), str_replace('Bundle', '', $directory->getBasename())]);
2222
}
2323
}
2424
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
namespace Softspring\CmsBundle\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
8+
/**
9+
* Sorts twig namespaces to manage priority:
10+
* - higher priority for project templates
11+
* - then bundles&plugins overrides
12+
* - less priority main bundles templates
13+
*/
14+
class SortTwigNamespaceTemplatesPass implements CompilerPassInterface
15+
{
16+
public function process(ContainerBuilder $container): void
17+
{
18+
$this->processNamespace($container, 'SfsCms', 'cms-bundle');
19+
$this->processNamespace($container, 'SfsMedia', 'media-bundle');
20+
}
21+
22+
private function processNamespace(ContainerBuilder $container, string $namespace, string $bundleDir): void
23+
{
24+
$projectDir = $container->getParameter('kernel.project_dir');
25+
26+
$twigFilesystemLoaderDefinition = $container->getDefinition('twig.loader.native_filesystem');
27+
28+
// get namespace paths and remove addPath
29+
$methodCalls = $twigFilesystemLoaderDefinition->getMethodCalls();
30+
$sfsNamespaceCalls = $this->getNamespacePaths($namespace, $methodCalls);
31+
$twigFilesystemLoaderDefinition->setMethodCalls(array_values($methodCalls));
32+
33+
// sort paths
34+
uasort($sfsNamespaceCalls, function (string $a, string $b) use ($namespace, $projectDir, $bundleDir): int {
35+
return $this->pathPriority($a, $namespace, $projectDir, $bundleDir) <=> $this->pathPriority($b, $namespace, $projectDir, $bundleDir);
36+
});
37+
38+
// add paths
39+
foreach ($sfsNamespaceCalls as $path) {
40+
$twigFilesystemLoaderDefinition->addMethodCall('addPath', [$path, $namespace]);
41+
}
42+
}
43+
44+
private function pathPriority(string $path, string $namespace, string $projectDir, string $bundleDir): int
45+
{
46+
if ($path === "$projectDir/templates/bundles/{$namespace}Bundle") {
47+
return 0;
48+
}
49+
50+
$bundlePath = realpath("$projectDir/vendor/softspring/$bundleDir");
51+
if ($bundlePath && str_starts_with($path, $bundlePath)) {
52+
return 2;
53+
}
54+
55+
return 1; // resto de bundles
56+
}
57+
58+
private function getNamespacePaths(string $namespace, array &$methodCalls): array
59+
{
60+
$paths = [];
61+
62+
foreach ($methodCalls as $i => $call) {
63+
if ('addPath' === $call[0] && (isset($call[1][1]) && $call[1][1] === $namespace)) {
64+
unset($methodCalls[$i]);
65+
$paths[] = $call[1][0];
66+
}
67+
}
68+
69+
return $paths;
70+
}
71+
}

src/SfsCmsBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Softspring\CmsBundle\DependencyInjection\Compiler\EsiCacheStrategyPass;
1010
use Softspring\CmsBundle\DependencyInjection\Compiler\InjectWebDebugToolbarListenerPass;
1111
use Softspring\CmsBundle\DependencyInjection\Compiler\ResolveDoctrineTargetEntityPass;
12+
use Softspring\CmsBundle\DependencyInjection\Compiler\SortTwigNamespaceTemplatesPass;
1213
use Symfony\Component\DependencyInjection\ContainerBuilder;
1314
use Symfony\Component\HttpKernel\Bundle\Bundle;
1415

@@ -34,6 +35,7 @@ public function build(ContainerBuilder $container): void
3435
$container->addCompilerPass(new AddTwigNamespacesPass());
3536
$container->addCompilerPass(new AddCollectionTranslationsPass());
3637
$container->addCompilerPass(new EsiCacheStrategyPass());
38+
$container->addCompilerPass(new SortTwigNamespaceTemplatesPass(), priority: -100);
3739
}
3840

3941
private function addRegisterMappingsPass(ContainerBuilder $container, array $mappings, string|bool $enablingParameter = false): void

0 commit comments

Comments
 (0)