Skip to content

Commit 43e1aa7

Browse files
committed
feature #18533 [FrameworkBundle] Wire PhpArrayAdapter with a new cache warmer for annotations (tgalopin)
This PR was squashed before being merged into the 3.2-dev branch (closes #18533). Discussion ---------- [FrameworkBundle] Wire PhpArrayAdapter with a new cache warmer for annotations | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | WIP | Fixed tickets | - | License | MIT | Doc PR | - Depends on symfony/symfony#18825 and symfony/symfony#18823 This PR implements the usage of the new OpCacheAdapter in the annotations caching system. The idea to use this adapter as much as possible in Symfony (validator, serializer, ...). These other implementations will be the object of different PRs. Commits ------- f950a2b [FrameworkBundle] Wire PhpArrayAdapter with a new cache warmer for annotations
2 parents 3399e0e + d81b03c commit 43e1aa7

File tree

7 files changed

+157
-10
lines changed

7 files changed

+157
-10
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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\FrameworkBundle\CacheWarmer;
13+
14+
use Doctrine\Common\Annotations\CachedReader;
15+
use Doctrine\Common\Annotations\Reader;
16+
use Psr\Cache\CacheItemPoolInterface;
17+
use Symfony\Component\Cache\Adapter\AdapterInterface;
18+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
19+
use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
20+
use Symfony\Component\Cache\Adapter\ProxyAdapter;
21+
use Symfony\Component\Cache\DoctrineProvider;
22+
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
23+
24+
/**
25+
* Warms up annotation caches for classes found in composer's autoload class map
26+
* and declared in DI bundle extensions using the addAnnotatedClassesToCache method.
27+
*
28+
* @author Titouan Galopin <galopintitouan@gmail.com>
29+
*/
30+
class AnnotationsCacheWarmer implements CacheWarmerInterface
31+
{
32+
private $annotationReader;
33+
private $phpArrayFile;
34+
private $fallbackPool;
35+
36+
/**
37+
* @param Reader $annotationReader
38+
* @param string $phpArrayFile The PHP file where annotations are cached.
39+
* @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered annotations are cached.
40+
*/
41+
public function __construct(Reader $annotationReader, $phpArrayFile, CacheItemPoolInterface $fallbackPool)
42+
{
43+
$this->annotationReader = $annotationReader;
44+
$this->phpArrayFile = $phpArrayFile;
45+
if (!$fallbackPool instanceof AdapterInterface) {
46+
$fallbackPool = new ProxyAdapter($fallbackPool);
47+
}
48+
$this->fallbackPool = $fallbackPool;
49+
}
50+
51+
/**
52+
* {@inheritdoc}
53+
*/
54+
public function warmUp($cacheDir)
55+
{
56+
$adapter = new PhpArrayAdapter($this->phpArrayFile, $this->fallbackPool);
57+
$annotatedClassPatterns = $cacheDir.'/annotations.map';
58+
59+
if (!is_file($annotatedClassPatterns)) {
60+
$adapter->warmUp(array());
61+
62+
return;
63+
}
64+
65+
$annotatedClasses = include $annotatedClassPatterns;
66+
67+
$arrayPool = new ArrayAdapter(0, false);
68+
$reader = new CachedReader($this->annotationReader, new DoctrineProvider($arrayPool));
69+
70+
foreach ($annotatedClasses as $class) {
71+
$this->readAllComponents($reader, $class);
72+
}
73+
74+
$values = $arrayPool->getValues();
75+
$adapter->warmUp($values);
76+
77+
foreach ($values as $k => $v) {
78+
$item = $this->fallbackPool->getItem($k);
79+
$this->fallbackPool->saveDeferred($item->set($v));
80+
}
81+
$this->fallbackPool->commit();
82+
}
83+
84+
/**
85+
* {@inheritdoc}
86+
*/
87+
public function isOptional()
88+
{
89+
return true;
90+
}
91+
92+
private function readAllComponents(Reader $reader, $class)
93+
{
94+
$reflectionClass = new \ReflectionClass($class);
95+
$reader->getClassAnnotations($reflectionClass);
96+
97+
foreach ($reflectionClass->getMethods() as $reflectionMethod) {
98+
$reader->getMethodAnnotations($reflectionMethod);
99+
}
100+
101+
foreach ($reflectionClass->getProperties() as $reflectionProperty) {
102+
$reader->getPropertyAnnotations($reflectionProperty);
103+
}
104+
}
105+
}

DependencyInjection/Configuration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ private function addAnnotationsSection(ArrayNodeDefinition $rootNode)
594594
->info('annotation configuration')
595595
->addDefaultsIfNotSet()
596596
->children()
597-
->scalarNode('cache')->defaultValue('file')->end()
597+
->scalarNode('cache')->defaultValue('php_array')->end()
598598
->scalarNode('file_cache_dir')->defaultValue('%kernel.cache_dir%/annotations')->end()
599599
->booleanNode('debug')->defaultValue($this->debug)->end()
600600
->end()

DependencyInjection/FrameworkExtension.php

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ public function load(array $configs, ContainerBuilder $container)
168168
$definition->replaceArgument(1, null);
169169
}
170170

171+
$this->addAnnotatedClassesToCompile(array(
172+
'**Bundle\\Controller\\',
173+
'**Bundle\\Entity\\',
174+
175+
// Added explicitly so that we don't rely on the class map being dumped to make it work
176+
'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller',
177+
));
178+
171179
$this->addClassesToCompile(array(
172180
'Symfony\\Component\\Config\\ConfigCache',
173181
'Symfony\\Component\\Config\\FileLocator',
@@ -905,8 +913,22 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde
905913
$loader->load('annotations.xml');
906914

907915
if ('none' !== $config['cache']) {
908-
if ('file' === $config['cache']) {
916+
$cacheService = $config['cache'];
917+
918+
if ('php_array' === $config['cache']) {
919+
$cacheService = 'annotations.cache';
920+
921+
// Enable warmer only if PHP array is used for cache
922+
$definition = $container->findDefinition('annotations.cache_warmer');
923+
$definition->addTag('kernel.cache_warmer');
924+
925+
$this->addClassesToCompile(array(
926+
'Symfony\Component\Cache\Adapter\PhpArrayAdapter',
927+
'Symfony\Component\Cache\DoctrineProvider',
928+
));
929+
} elseif ('file' === $config['cache']) {
909930
$cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']);
931+
910932
if (!is_dir($cacheDir) && false === @mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
911933
throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $cacheDir));
912934
}
@@ -915,11 +937,13 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde
915937
->getDefinition('annotations.filesystem_cache')
916938
->replaceArgument(0, $cacheDir)
917939
;
940+
941+
$cacheService = 'annotations.filesystem_cache';
918942
}
919943

920944
$container
921945
->getDefinition('annotations.cached_reader')
922-
->replaceArgument(1, new Reference('file' !== $config['cache'] ? $config['cache'] : 'annotations.filesystem_cache'))
946+
->replaceArgument(1, new Reference($cacheService))
923947
->replaceArgument(2, $config['debug'])
924948
->addAutowiringType(Reader::class)
925949
;
@@ -1129,10 +1153,8 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
11291153
}
11301154

11311155
$this->addClassesToCompile(array(
1132-
'Psr\Cache\CacheItemInterface',
1133-
'Psr\Cache\CacheItemPoolInterface',
1134-
'Symfony\Component\Cache\Adapter\AdapterInterface',
1135-
'Symfony\Component\Cache\Adapter\AbstractAdapter',
1156+
'Symfony\Component\Cache\Adapter\ApcuAdapter',
1157+
'Symfony\Component\Cache\Adapter\FilesystemAdapter',
11361158
'Symfony\Component\Cache\CacheItem',
11371159
));
11381160
}

Resources/config/annotations.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@
1919
<argument /><!-- Cache-Directory -->
2020
</service>
2121

22+
<service id="annotations.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\AnnotationsCacheWarmer" public="false">
23+
<argument type="service" id="annotations.reader" />
24+
<argument>%kernel.cache_dir%/annotations.php</argument>
25+
<argument type="service" id="cache.annotations" />
26+
</service>
27+
28+
<service id="annotations.cache" class="Symfony\Component\Cache\DoctrineProvider" public="false">
29+
<argument type="service">
30+
<service class="Symfony\Component\Cache\Adapter\PhpArrayAdapter">
31+
<factory class="Symfony\Component\Cache\Adapter\PhpArrayAdapter" method="create" />
32+
<argument>%kernel.cache_dir%/annotations.php</argument>
33+
<argument type="service" id="cache.annotations" />
34+
</service>
35+
</argument>
36+
</service>
37+
2238
<service id="annotation_reader" alias="annotations.reader" />
2339
</services>
2440
</container>

Resources/config/cache.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
<tag name="cache.pool" />
2323
</service>
2424

25+
<service id="cache.annotations" parent="cache.system" public="false">
26+
<tag name="cache.pool" />
27+
</service>
28+
2529
<service id="cache.adapter.system" class="Symfony\Component\Cache\Adapter\AdapterInterface" abstract="true">
2630
<factory class="Symfony\Component\Cache\Adapter\AbstractAdapter" method="createSystemCache" />
2731
<tag name="cache.pool" clearer="cache.default_clearer" />

Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ protected static function getBundleDefaultConfig()
214214
'cache' => 'validator.mapping.cache.symfony',
215215
),
216216
'annotations' => array(
217-
'cache' => 'file',
217+
'cache' => 'php_array',
218218
'file_cache_dir' => '%kernel.cache_dir%/annotations',
219219
'debug' => true,
220220
),

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
"require": {
1919
"php": ">=5.5.9",
2020
"symfony/asset": "~2.8|~3.0",
21-
"symfony/cache": "~3.1",
21+
"symfony/cache": "~3.2",
2222
"symfony/class-loader": "~3.2",
2323
"symfony/dependency-injection": "~3.2",
2424
"symfony/config": "~2.8|~3.0",
2525
"symfony/event-dispatcher": "~2.8|~3.0",
2626
"symfony/http-foundation": "~3.1",
27-
"symfony/http-kernel": "~3.1.2|~3.2",
27+
"symfony/http-kernel": "~3.2",
2828
"symfony/polyfill-mbstring": "~1.0",
2929
"symfony/filesystem": "~2.8|~3.0",
3030
"symfony/finder": "~2.8|~3.0",

0 commit comments

Comments
 (0)