8000 [TwigBundle] Use `kernel.build_dir` to store the templates known at b… · symfony/symfony@4289c16 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4289c16

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 b5ee977 commit 4289c16

File tree

16 files changed

+203
-18
lines changed

16 files changed

+203
-18
lines changed

src/Symfony/Bundle/TwigBundle/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ CHANGELOG
55
---
66

77
* Mark class `TemplateCacheWarmer` as `final`
8+
* Create `ChainCache` to store warmed-up cache in `kernel.build_dir` and runtime cache in `cache_dir`
9+
* Make `TemplateCacheWarmer` use `kernel.build_dir` instead of `cache_dir`
810

911
7.0
1012
---
Lines changed: 80 additions & 0 deletions
< 10000 td data-grid-cell-id="diff-45cf19555209d7fe5c37f8bf77071a03834cec3041564d2558b28d0536cc5c5c-empty-44-2" data-line-anchor="diff-45cf19555209d7fe5c37f8bf77071a03834cec3041564d2558b28d0536cc5c5cR44" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-additionLine-bgColor, var(--diffBlob-addition-bgColor-line));padding-right:24px" tabindex="-1" valign="top" class="focusable-grid-cell diff-text-cell right-side-diff-cell pt-4 left-side">+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\TwigBundle\Cache;
13+
14+
use Twig\Cache\CacheInterface;
15+
16+
/**
17+
* Chains several caches together.
18+
*
19+
* Cached items are fetched from the first cache having them in its data store.
20+
* They are saved and deleted in all adapters at once.
21+
*/
22+
class ChainCache implements CacheInterface
23+
{
24+
/**
25+
* @param CacheInterface[] $caches The ordered list of caches used to store and fetch cached items
26+
*/
27+
public function __construct(private array $caches)
28+
{
29+
if ([] === $caches) {
30+
throw new \InvalidArgumentException('At least one cache must be specified.');
31+
}
32+
33+
foreach ($caches as $cache) {
34+
if (!$cache instanceof CacheInterface) {
35+
throw new \InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', get_debug_type($cache), CacheInterface::class));
36+
}
37+
}
38+
}
39+
40+
public function generateKey(string $name, string $className): string
41+
{
42+
return $name.'#'.$className;
43+
}
44
45+
public function write(string $key, string $content): void
46+
{
47+
[$name, $className] = explode('#', $key, 2);
48+
49+
foreach ($this->caches as $cache) {
50+
$cache->write($cache->generateKey($name, $className), $content);
51+
}
52+
}
53+
54+
public function load(string $key): void
55+
{
56+
[$name, $className] = explode('#', $key, 2);
57+
58+
foreach ($this->caches as $cache) {
59+
$cache->load($cache->generateKey($name, $className));
60+
61+
if (class_exists($className, false)) {
62+
break;
63+
}
64+
}
65+
}
66+
67+
public function getTimestamp(string $key): int
68+
{
69+
[$name, $className] = explode('#', $key, 2);
70+
71+
foreach ($this->caches as $cache) {
72+
$timestamp = $cache->getTimestamp($cache->generateKey($name, $className));
73+
if ($timestamp > 0) {
74+
return $timestamp;
75+
}
76+
}
77+
78+
return 0;
79+
}
80+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\TwigBundle\Cache;
13+
14+
use Twig\Cache\FilesystemCache;
15+
16+
/**
17+
* Implements a cache on the filesystem that can only be read, not written to.
18+
*/
19+
class ReadOnlyFilesystemCache extends FilesystemCache
20+
{
21+
public function write(string $key, string $content): void
22+
{
23+
// Do nothing with the content, it's a read-only filesystem.
24+
}
25+
}

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,26 @@
2626
*/
2727
class TemplateCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface
2828
{
29-
private ContainerInterface $container;
3029
private Environment $twig;
31-
private iterable $iterator;
3230

33-
public function __construct(ContainerInterface $container, iterable $iterator)
31+
public function __construct(private ContainerInterface $container, private iterable $iterator, private string $cacheFolder = 'twig')
3432
{
35-
// As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected.
36-
$this->container = $container;
37-
$this->iterator = $iterator;
33+
if (\func_num_args() < 3) {
34+
trigger_deprecation('symfony/twig-bundle', '7.1', 'The "string $cacheFolder" argument of "%s()" method will not be optional anymore in version 8.0, not defining it is deprecated.', __METHOD__);
35+
}
3836
}
3937

4038
public function warmUp(string $cacheDir, ?string $buildDir = null): array
4139
{
40+
if (!$buildDir) {
41+
return [];
42+
}
43+
4244
$this->twig ??= $this->container->get('twig');
4345

46+
$originalCache = $this->twig->getCache();
47+
$this->twig->setCache($buildDir.\DIRECTORY_SEPARATOR.$this->cacheFolder);
48+
4449
foreach ($this->iterator as $template) {
4550
try {
4651
$this->twig->load($template);
@@ -56,6 +61,8 @@ public function warmUp(string $cacheDir, ?string $buildDir = null): array
5661
}
5762
}
5863

64+
$this->twig->setCache($originalCache);
65+
5966
return [];
6067
}
6168

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,16 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode): void
130130
->scalarNode('autoescape_service')->defaultNull()->end()
131131
->scalarNode('autoescape_service_method')->defaultNull()->end()
132132
->scalarNode('base_template_class')->example('Twig\Template')->cannotBeEmpty()->end()
133-
->scalarNode('cache')->defaultValue('%kernel.cache_dir%/twig')->end()
133+
->scalarNode('cache')
134+
->validate()
135+
->ifTrue(fn ($v) => !\is_bool($v))
136+
->then(function ($v) {
137+
trigger_deprecation('symfony/twig-bundle', '7.1', 'Setting the "twig.cache" configuration option to a string is deprecated. It will only accept boolean values to enable or disable the cache in version 8.0.');
138+
139+
return $v;
140+
})
141+
->end()
142+
->end()
134143
->scalarNode('charset')->defaultValue('%kernel.charset%')->end()
135144
->booleanNode('debug')->defaultValue('%kernel.debug%')->end()
136145
->booleanNode('strict_variables')->defaultValue('%kernel.debug%')->end()

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

Lines changed: 16 additions & 4 deletions
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\Extension\ExtensionInterface;
2930
use Twig\Extension\RuntimeExtensionInterface;
3031
use Twig\Loader\LoaderInterface;
@@ -153,6 +154,21 @@ public function load(array $configs, ContainerBuilder $container): void
153154
}
154155
}
155156

157+
if (!isset($config['cache']) || true === $config['cache']) {
158+
$config['cache'] = new Reference('twig.template_cache.chain');
159+
160+
$cacheOptions = ($config['auto_reload'] ?? true) ? FilesystemCache::FORCE_BYTECODE_INVALIDATION : 0;
161+
$container->getDefinition('twig.template_cache.runtime_cache')->replaceArgument(1, $cacheOptions);
162+
} else {
163+
$container->removeDefinition('twig.template_cache.chain');
164+
$container->removeDefinition('twig.template_cache.runtime_cache');
165+
$container->removeDefinition('twig.template_cache.readonly_cache');
166+
167+
if (false === $config['cache']) {
168+
$container->removeDefinition('twig.template_cache_warmer');
169+
}
170+
}
171+
156172
if (isset($config['autoescape_service'])) {
157173
$config['autoescape'] = [new Reference($config['autoescape_service']), $config['autoescape_service_method'] ?? '__invoke'];
158174
} else {
@@ -173,10 +189,6 @@ public function load(array $configs, ContainerBuilder $container): void
173189
$container->registerForAutoconfiguration(ExtensionInterface::class)->addTag('twig.extension');
174190
$container->registerForAutoconfiguration(LoaderInterface::class)->addTag('twig.loader');
175191
$container->registerForAutoconfiguration(RuntimeExtensionInterface::class)->addTag('twig.runtime');
176-
177-
if (false === $config['cache']) {
178-
$container->removeDefinition('twig.template_cache_warmer');
179-
}
180192
}
181193

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

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
use Symfony\Bridge\Twig\Extension\WorkflowExtension;
3333
use Symfony\Bridge\Twig\Extension\YamlExtension;
3434
use Symfony\Bridge\Twig\Translation\TwigExtractor;
35+
use Symfony\Bundle\TwigBundle\Cache\ChainCache;
36+
use Symfony\Bundle\TwigBundle\Cache\ReadOnlyFilesystemCache;
3537
use Symfony\Bundle\TwigBundle\CacheWarmer\TemplateCacheWarmer;
3638
use Symfony\Bundle\TwigBundle\DependencyInjection\Configurator\EnvironmentConfigurator;
3739
use Symfony\Bundle\TwigBundle\TemplateIterator;
@@ -78,8 +80,17 @@
7880
->set('twig.template_iterator', TemplateIterator::class)
7981
->args([service('kernel'), abstract_arg('Twig paths'), param('twig.default_path'), abstract_arg('File name pattern')])
8082

83+
->set('twig.template_cache.runtime_cache', FilesystemCache::class)
84+
->args([param('kernel.cache_dir').'/twig', abstract_arg('Twig filesystem cache options')])
85+
86+
->set('twig.template_cache.readonly_cache', ReadOnlyFilesystemCache::class)
87+
->args([param('kernel.build_dir').'/twig'])
88+
89+
->set('twig.template_cache.chain', ChainCache::class)
90+
->args([[service('twig.template_cache.runtime_cache'), service('twig.template_cache.readonly_cache')]])
91+
8192
->set('twig.template_cache_warmer', TemplateCacheWarmer::class)
82-
->args([service(ContainerInterface::class), service('twig.template_iterator')])
93+
->args([service(ContainerInterface::class), service('twig.template_iterator'), 'twig'])
8394
->tag('kernel.cache_warmer')
8495
->tag('container.service_subscriber', ['id' => 'twig'])
8596

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

Lines changed: 0 additions & 1 deletion
D564
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
],
1313
'auto_reload' => true,
1414
'base_template_class' => 'stdClass',
15-
'cache' => '/tmp',
1615
'charset' => 'ISO-8859-1',
1716
'debug' => true,
1817
'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+
]);

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" base-template-class="stdClass" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true">
9+
<twig:config auto-reload="true" base-template-class="stdClass" 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)
0