Skip to content

Commit a0bbca5

Browse files
committed
[TwigBundle] Use kernel.build_dir to store the templates known at build time
Signed-off-by: Quentin Devos <4972091+Okhoshi@users.noreply.github.com>
1 parent 58a14ab commit a0bbca5

File tree

19 files changed

+192
-24
lines changed

19 files changed

+192
-24
lines changed

src/Symfony/Bundle/TwigBundle/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ CHANGELOG
77
* Enable `#[AsTwigFilter]`, `#[AsTwigFunction]` and `#[AsTwigTest]` attributes
88
to configure extensions on runtime classes
99
* Add support for a `twig` validator
10+
* Use `ChainCache` to store warmed-up cache in `kernel.build_dir` and runtime cache in `kernel.cache_dir`
11+
* Make `TemplateCacheWarmer` use `kernel.build_dir` instead of `kernel.cache_dir`
1012

1113
7.1
1214
---

src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
use Psr\Container\ContainerInterface;
1515
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
1616
use Symfony\Contracts\Service\ServiceSubscriberInterface;
17+
use Twig\Cache\CacheInterface;
18+
use Twig\Cache\NullCache;
1719
use Twig\Environment;
1820
use Twig\Error\Error;
1921

@@ -34,26 +36,48 @@ class TemplateCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInte
3436
public function __construct(
3537
private ContainerInterface $container,
3638
private iterable $iterator,
39+
private ?CacheInterface $cache = null,
3740
) {
3841
}
3942

4043
public function warmUp(string $cacheDir, ?string $buildDir = null): array
4144
{
4245
$this->twig ??= $this->container->get('twig');
4346

44-
foreach ($this->iterator as $template) {
45-
try {
46-
$this->twig->load($template);
47-
} catch (Error) {
47+
$originalCache = $this->twig->getCache();
48+
if ($originalCache instanceof NullCache) {
49+
// There's no point to warm up a cache that won't be used afterward
50+
return [];
51+
}
52+
53+
if (null !== $this->cache) {
54+
if (!$buildDir) {
4855
/*
49-
* Problem during compilation, give up for this template (e.g. syntax errors).
50-
* Failing silently here allows to ignore templates that rely on functions that aren't available in
51-
* the current environment. For example, the WebProfilerBundle shouldn't be available in the prod
52-
* environment, but some templates that are never used in prod might rely on functions the bundle provides.
53-
* As we can't detect which templates are "really" important, we try to load all of them and ignore
54-
* errors. Error checks may be performed by calling the lint:twig command.
56+
* The cache has already been warmup during the build of the container, when $buildDir was set.
5557
*/
58+
return [];
59+
}
60+
// Swap the cache for the warmup as the Twig Environment has the ChainCache injected
61+
$this->twig->setCache($this->cache);
62+
}
63+
64+
try {
65+
foreach ($this->iterator as $template) {
66+
try {
67+
$this->twig->load($template);
68+
} catch (Error) {
69+
/*
70+
* Problem during compilation, give up for this template (e.g. syntax errors).
71+
* Failing silently here allows to ignore templates that rely on functions that aren't available in
72+
* the current environment. For example, the WebProfilerBundle shouldn't be available in the prod
73+
* environment, but some templates that are never used in prod might rely on functions the bundle provides.
74+
* As we can't detect which templates are "really" important, we try to load all of them and ignore
75+
* errors. Error checks may be performed by calling the lint:twig command.
76+
*/
77+
}
5678
}
79+
} finally {
80+
$this->twig->setCache($originalCache);
5781
}
5882

5983
return [];

src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode): void
134134
->example('Twig\Template')
135135
->cannotBeEmpty()
136136
->end()
137-
->scalarNode('cache')->defaultValue('%kernel.cache_dir%/twig')->end()
137+
->scalarNode('cache')->defaultTrue()->end()
138138
->scalarNode('charset')->defaultValue('%kernel.charset%')->end()
139139
->booleanNode('debug')->defaultValue('%kernel.debug%')->end()
140140
->booleanNode('strict_variables')->defaultValue('%kernel.debug%')->end()

src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Twig\Attribute\AsTwigFilter;
3131
use Twig\Attribute\AsTwigFunction;
3232
use Twig\Attribute\AsTwigTest;
33+
use Twig\Cache\FilesystemCache;
3334
use Twig\Environment;
3435
use Twig\Extension\ExtensionInterface;
3536
use Twig\Extension\RuntimeExtensionInterface;
@@ -167,6 +168,31 @@ public function load(array $configs, ContainerBuilder $container): void
167168
}
168169
}
169170

171+
if (true === $config['cache']) {
172+
$autoReloadOrDefault = $container->getParameterBag()->resolveValue($config['auto_reload'] ?? $config['debug']);
173+
$cacheDir = $container->getParameter('kernel.cache_dir');
174+
$buildDir = $container->getParameter('kernel.build_dir');
175+
176+
if ($autoReloadOrDefault || $cacheDir === $buildDir) {
177+
$config['cache'] = '%kernel.cache_dir%/twig';
178+
}
179+
}
180+
181+
if (true === $config['cache']) {
182+
$config['cache'] = new Reference('twig.template_cache.chain');
183+
} else {
184+
$container->removeDefinition('twig.template_cache.chain');
185+
$container->removeDefinition('twig.template_cache.runtime_cache');
186+
$container->removeDefinition('twig.template_cache.readonly_cache');
187+
$container->removeDefinition('twig.template_cache.warmup_cache');
188+
189+
if (false === $config['cache']) {
190+
$container->removeDefinition('twig.template_cache_warmer');
191+
} else {
192+
$container->getDefinition('twig.template_cache_warmer')->replaceArgument(2, null);
193+
}
194+
}
195+
170196
if (isset($config['autoescape_service'])) {
171197
$config['autoescape'] = [new Reference($config['autoescape_service']), $config['autoescape_service_method'] ?? '__invoke'];
172198
} else {
@@ -191,10 +217,6 @@ public function load(array $configs, ContainerBuilder $container): void
191217
$container->registerAttributeForAutoconfiguration(AsTwigFilter::class, AttributeExtensionPass::autoconfigureFromAttribute(...));
192218
$container->registerAttributeForAutoconfiguration(AsTwigFunction::class, AttributeExtensionPass::autoconfigureFromAttribute(...));
193219
$container->registerAttributeForAutoconfiguration(AsTwigTest::class, AttributeExtensionPass::autoconfigureFromAttribute(...));
194-
195-
if (false === $config['cache']) {
196-
$container->removeDefinition('twig.template_cache_warmer');
197-
}
198220
}
199221

200222
private function getBundleTemplatePaths(ContainerBuilder $container, array $config): array

src/Symfony/Bundle/TwigBundle/Resources/config/twig.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
use Symfony\Bundle\TwigBundle\CacheWarmer\TemplateCacheWarmer;
3737
use Symfony\Bundle\TwigBundle\DependencyInjection\Configurator\EnvironmentConfigurator;
3838
use Symfony\Bundle\TwigBundle\TemplateIterator;
39+
use Twig\Cache\ChainCache;
3940
use Twig\Cache\FilesystemCache;
41+
use Twig\Cache\ReadOnlyFilesystemCache;
4042
use Twig\Environment;
4143
use Twig\Extension\CoreExtension;
4244
use Twig\Extension\DebugExtension;
@@ -79,8 +81,24 @@
7981
->set('twig.template_iterator', TemplateIterator::class)
8082
->args([service('kernel'), abstract_arg('Twig paths'), param('twig.default_path'), abstract_arg('File name pattern')])
8183

84+
->set('twig.template_cache.runtime_cache', FilesystemCache::class)
85+
->args([param('kernel.cache_dir').'/twig'])
86+
87+
->set('twig.template_cache.readonly_cache', ReadOnlyFilesystemCache::class)
88+
->args([param('kernel.build_dir').'/twig'])
89+
90+
->set('twig.template_cache.warmup_cache', FilesystemCache::class)
91+
->args([param('kernel.build_dir').'/twig'])
92+
93+
->set('twig.template_cache.chain', ChainCache::class)
94+
->args([[service('twig.template_cache.readonly_cache'), service('twig.template_cache.runtime_cache')]])
95+
8296
->set('twig.template_cache_warmer', TemplateCacheWarmer::class)
83-
->args([service(ContainerInterface::class), service('twig.template_iterator')])
97+
->args([
98+
service(ContainerInterface::class),
99+
service('twig.template_iterator'),
100+
service('twig.template_cache.warmup_cache'),
101+
])
84102
->tag('kernel.cache_warmer')
85103
->tag('container.service_subscriber', ['id' => 'twig'])
86104

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
'pi' => 3.14,
1111
'bad' => ['key' => 'foo'],
1212
],
13-
'auto_reload' => true,
14-
'cache' => '/tmp',
13+
'auto_reload' => false,
1514
'charset' => 'ISO-8859-1',
1615
'debug' => true,
1716
'strict_variables' => true,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
$container->loadFromExtension('twig', [
4+
'cache' => false,
5+
]);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
$container->loadFromExtension('twig', [
4+
'cache' => 'random-path',
5+
]);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
$container->loadFromExtension('twig', [
4+
'cache' => true,
5+
'auto_reload' => false,
6+
]);

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/extra.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
77
http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd">
88

9-
<twig:config auto-reload="true" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true">
9+
<twig:config auto-reload="true" charset="ISO-8859-1" debug="true" strict-variables="true">
1010
<twig:path namespace="namespace3">namespaced_path3</twig:path>
1111
</twig:config>
1212
</container>

0 commit comments

Comments
 (0)