Skip to content

Commit 3483575

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 b6c7abc commit 3483575

File tree

10 files changed

+79
-24
lines changed

10 files changed

+79
-24
lines changed

src/Symfony/Bundle/TwigBundle/CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG
22
=========
33

4+
7.2
5+
---
6+
7+
* Use `ChainCache` to store warmed-up cache in `kernel.build_dir` and runtime cache in `kernel.cache_dir`
8+
* Make `TemplateCacheWarmer` use `kernel.build_dir` instead of `kernel.cache_dir`
9+
410
7.1
511
---
612

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

+28-12
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Psr\Container\ContainerInterface;
1515
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
1616
use Symfony\Contracts\Service\ServiceSubscriberInterface;
17+
use Twig\Cache\CacheInterface;
1718
use Twig\Environment;
1819
use Twig\Error\Error;
1920

@@ -34,26 +35,41 @@ class TemplateCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInte
3435
public function __construct(
3536
private ContainerInterface $container,
3637
private iterable $iterator,
38+
private ?CacheInterface $cache = null,
3739
) {
3840
}
3941

4042
public function warmUp(string $cacheDir, ?string $buildDir = null): array
4143
{
44+
if (!$buildDir) {
45+
return [];
46+
}
47+
4248
$this->twig ??= $this->container->get('twig');
4349

44-
foreach ($this->iterator as $template) {
45-
try {
46-
$this->twig->load($template);
47-
} catch (Error) {
48-
/*
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.
55-
*/
50+
$originalCache = $this->twig->getCache();
51+
if (null !== $this->cache) {
52+
// Swap the cache for the warmup as the Twig Environment has the ChainCache injected
53+
$this->twig->setCache($this->cache);
54+
}
55+
56+
try {
57+
foreach ($this->iterator as $template) {
58+
try {
59+
$this->twig->load($template);
60+
} catch (Error) {
61+
/*
62+
* Problem during compilation, give up for this template (e.g. syntax errors).
63+
* Failing silently here allows to ignore templates that rely on functions that aren't available in
64+
* the current environment. For example, the WebProfilerBundle shouldn't be available in the prod
65+
* environment, but some templates that are never used in prod might rely on functions the bundle provides.
66+
* As we can't detect which templates are "really" important, we try to load all of them and ignore
67+
* errors. Error checks may be performed by calling the lint:twig command.
68+
*/
69+
}
5670
}
71+
} finally {
72+
$this->twig->setCache($originalCache);
5773
}
5874

5975
return [];

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ 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')
138+
->setDeprecated('symfony/twig-bundle', '7.2', 'Setting the "%path%.%node%" configuration option is deprecated. It will be removed in version 8.0.')
139+
->end()
138140
->scalarNode('charset')->defaultValue('%kernel.charset%')->end()
139141
->booleanNode('debug')->defaultValue('%kernel.debug%')->end()
140142
->booleanNode('strict_variables')->defaultValue('%kernel.debug%')->end()

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

+19-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Symfony\Component\Translation\LocaleSwitcher;
2626
use Symfony\Component\Translation\Translator;
2727
use Symfony\Contracts\Service\ResetInterface;
28+
use Twig\Cache\FilesystemCache;
2829
use Twig\Environment;
2930
use Twig\Extension\ExtensionInterface;
3031
use Twig\Extension\RuntimeExtensionInterface;
@@ -158,6 +159,24 @@ public function load(array $configs, ContainerBuilder $container): void
158159
}
159160
}
160161

162+
if (!isset($config['cache']) || true === $config['cache']) {
163+
$config['cache'] = new Reference('twig.template_cache.chain');
164+
165+
$cacheOptions = ($config['auto_reload'] ?? true) ? FilesystemCache::FORCE_BYTECODE_INVALIDATION : 0;
166+
$container->getDefinition('twig.template_cache.runtime_cache')->replaceArgument(1, $cacheOptions);
167+
} else {
168+
$container->removeDefinition('twig.template_cache.chain');
169+
$container->removeDefinition('twig.template_cache.runtime_cache');
170+
$container->removeDefinition('twig.template_cache.readonly_cache');
171+
$container->removeDefinition('twig.template_cache.warmup_cache');
172+
173+
if (false === $config['cache']) {
174+
$container->removeDefinition('twig.template_cache_warmer');
175+
} else {
176+
$container->getDefinition('twig.template_cache_warmer')->replaceArgument(2, null);
177+
}
178+
}
179+
161180
if (isset($config['autoescape_service'])) {
162181
$config['autoescape'] = [new Reference($config['autoescape_service']), $config['autoescape_service_method'] ?? '__invoke'];
163182
} else {
@@ -178,10 +197,6 @@ public function load(array $configs, ContainerBuilder $container): void
178197
$container->registerForAutoconfiguration(ExtensionInterface::class)->addTag('twig.extension');
179198
$container->registerForAutoconfiguration(LoaderInterface::class)->addTag('twig.loader');
180199
$container->registerForAutoconfiguration(RuntimeExtensionInterface::class)->addTag('twig.runtime');
181-
182-
if (false === $config['cache']) {
183-
$container->removeDefinition('twig.template_cache_warmer');
184-
}
185200
}
186201

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

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

+19-1
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', abstract_arg('Twig filesystem cache options')])
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.runtime_cache'), service('twig.template_cache.readonly_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

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
'bad' => ['key' => 'foo'],
1212
],
1313
'auto_reload' => true,
14-
'cache' => '/tmp',
1514
'charset' => 'ISO-8859-1',
1615
'debug' => true,
1716
'strict_variables' => true,

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

+1-1
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>

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

+1-1
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" default-path="%kernel.project_dir%/Fixtures/templates">
9+
<twig:config auto-reload="true" charset="ISO-8859-1" debug="true" strict-variables="true" default-path="%kernel.project_dir%/Fixtures/templates">
1010
<twig:form-theme>MyBundle::form.html.twig</twig:form-theme>
1111
<twig:global key="foo" id="bar" type="service" />
1212
<twig:global key="baz">@@qux</twig:global>

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

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ twig:
77
pi: 3.14
88
bad: {key: foo}
99
auto_reload: true
10-
cache: /tmp
1110
charset: ISO-8859-1
1211
debug: true
1312
strict_variables: true

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function testLoadEmptyConfiguration()
4747

4848
// Twig options
4949
$options = $container->getDefinition('twig')->getArgument(1);
50-
$this->assertEquals('%kernel.cache_dir%/twig', $options['cache'], '->load() sets default value for cache option');
50+
$this->assertEquals(new Reference('twig.template_cache.chain'), $options['cache'], '->load() sets default value for cache option');
5151
$this->assertEquals('%kernel.charset%', $options['charset'], '->load() sets default value for charset option');
5252
$this->assertEquals('%kernel.debug%', $options['debug'], '->load() sets default value for debug option');
5353

@@ -95,7 +95,7 @@ public function testLoadFullConfiguration(string $format)
9595
$this->assertTrue($options['auto_reload'], '->load() sets the auto_reload option');
9696
$this->assertSame('name', $options['autoescape'], '->load() sets the autoescape option');
9797
$this->assertArrayNotHasKey('base_template_class', $options, '->load() does not set the base_template_class if none is provided');
98-
$this->assertEquals('/tmp', $options['cache'], '->load() sets the cache option');
98+
$this->assertEquals(new Reference('twig.template_cache.chain'), $options['cache'], '->load() sets the cache option');
9999
$this->assertEquals('ISO-8859-1', $options['charset'], '->load() sets the charset option');
100100
$this->assertTrue($options['debug'], '->load() sets the debug option');
101101
$this->assertTrue($options['strict_variables'], '->load() sets the strict_variables option');

0 commit comments

Comments
 (0)