Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7e9ce05

Browse files
committed
[FrameworkBundle] Introduce a cache warmer for Validator based on PhpArrayAdapter
1 parent 983b560 commit 7e9ce05

File tree

15 files changed

+269
-70
lines changed

15 files changed

+269
-70
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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 Psr\Cache\CacheItemPoolInterface;
15+
use Symfony\Component\Cache\Adapter\AdapterInterface;
16+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
17+
use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
18+
use Symfony\Component\Cache\Adapter\ProxyAdapter;
19+
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
20+
use Symfony\Component\Validator\Mapping\Cache\Psr6Cache;
21+
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
22+
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
23+
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
24+
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
25+
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
26+
use Symfony\Component\Validator\ValidatorBuilderInterface;
27+
28+
/**
29+
* Warms up XML and YAML validator metadata.
30+
*
31+
* @author Titouan Galopin <[email protected]>
32+
*/
33+
class ValidatorCacheWarmer implements CacheWarmerInterface
34+
{
35+
private $validatorBuilder;
36+
private $phpArrayFile;
37+
private $fallbackPool;
38+
39+
/**
40+
* @param array $bundles The application bundles to find validation metadata in.
41+
* @param string $phpArrayFile The PHP file where metadata are cached.
42+
* @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered metadata are cached.
43+
*/
44+
public function __construct(ValidatorBuilderInterface $validatorBuilder, $phpArrayFile, CacheItemPoolInterface $fallbackPool)
45+
{
46+
$this->validatorBuilder = $validatorBuilder;
47+
$this->phpArrayFile = $phpArrayFile;
48+
if (!$fallbackPool instanceof AdapterInterface) {
49+
$fallbackPool = new ProxyAdapter($fallbackPool);
50+
}
51+
$this->fallbackPool = $fallbackPool;
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
public function warmUp($cacheDir)
58+
{
59+
if (!method_exists($this->validatorBuilder, 'getLoaders')) {
60+
return;
61+
}
62+
63+
$adapter = new PhpArrayAdapter($this->phpArrayFile, $this->fallbackPool);
64+
$arrayPool = new ArrayAdapter(0, false);
65+
66+
$loader = $this->validatorBuilder->getLoaders();
67+
$metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loader), new Psr6Cache($arrayPool));
68+
69+
foreach ($this->extractSupportedLoaders(array($loader)) as $loader) {
70+
foreach ($loader->getClassesNames() as $mappedClass) {
71+
$metadataFactory->getMetadataFor($mappedClass);
72+
}
73+
}
74+
75+
$values = $arrayPool->getValues();
76+
$adapter->warmUp($values);
77+
78+
foreach ($values as $k => $v) {
79+
$item = $this->fallbackPool->getItem($k);
80+
$this->fallbackPool->saveDeferred($item->set($v));
81+
}
82+
$this->fallbackPool->commit();
83+
}
84+
85+
/**
86+
* {@inheritdoc}
87+
*/
88+
public function isOptional()
89+
{
90+
return true;
91+
}
92+
93+
/**
94+
* Filter an array of loaders to remove unsupported ones.
95+
*
96+
* @param LoaderInterface[] $loaders
97+
*
98+
* @return XmlFileLoader[]|YamlFileLoader[]
99+
*/
100+
private function extractSupportedLoaders(array $loaders)
101+
{
102+
$supportedLoaders = array();
103+
104+
foreach ($loaders as $loader) {
105+
if ($loader instanceof XmlFileLoader || $loader instanceof YamlFileLoader) {
106+
$supportedLoaders[] = $loader;
107+
} elseif ($loader instanceof LoaderChain) {
108+
$supportedLoaders = array_merge($supportedLoaders, $this->extractSupportedLoaders($loader->getDelegatedLoaders()));
109+
}
110+
}
111+
112+
return $supportedLoaders;
113+
}
114+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--- src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php 2016-08-01 09:19:38.230156146 +0000
2+
+++ src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php 2016-08-01 09:20:06.553933255 +0000
3+
@@ -12,7 +12,6 @@
4+
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
5+
6+
use Psr\Cache\CacheItemPoolInterface;
7+
-use Symfony\Bundle\FrameworkBundle\Validator\ValidatorMappingFilesFinder;
8+
use Symfony\Component\Cache\Adapter\AdapterInterface;
9+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
10+
use Symfony\Component\Cache\Adapter\PhpArrayAdapter;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode)
567567
->info('validation configuration')
568568
->canBeEnabled()
569569
->children()
570-
->scalarNode('cache')->defaultValue('validator.mapping.cache.symfony')->end()
570+
->scalarNode('cache')->end()
571571
->booleanNode('enable_annotations')->defaultFalse()->end()
572572
->arrayNode('static_method')
573573
->defaultValue(array('loadValidatorMetadata'))

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,13 +858,17 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
858858
}
859859
}
860860

861-
if (!$container->getParameter('kernel.debug')) {
861+
if (isset($config['cache']) && $config['cache']) {
862+
@trigger_error('The "framework.validation.cache" option is deprecated since Symfony 3.2 and will be removed in 4.0. Configure the "cache.validator" service under "framework.cache.pools" instead.', E_USER_DEPRECATED);
863+
862864
$container->setParameter(
863865
'validator.mapping.cache.prefix',
864866
'validator_'.$this->getKernelRootHash($container)
865867
);
866868

867869
$validatorBuilder->addMethodCall('setMetadataCache', array(new Reference($config['cache'])));
870+
} elseif (!$container->getParameter('kernel.debug')) {
871+
$validatorBuilder->addMethodCall('setMetadataCache', array(new Reference('validator.mapping.cache.symfony')));
868872
}
869873
}
870874

src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
<parameters>
88
<parameter key="validator.mapping.cache.prefix" />
9+
<parameter key="validator.mapping.cache.file">%kernel.cache_dir%/validation.php</parameter>
910
</parameters>
1011

1112
<services>
@@ -28,8 +29,21 @@
2829

2930
<service id="validator.mapping.class_metadata_factory" alias="validator" public="false" />
3031

31-
<service id="validator.mapping.cache.symfony" class="Symfony\Component\Validator\Mapping\Cache\Psr6Cache" public="false">
32+
<service id="validator.mapping.cache_warmer" class="Symfony\Bundle\FrameworkBundle\CacheWarmer\ValidatorCacheWarmer" public="false">
33+
<argument type="service" id="validator.builder" />
34+
<argument>%validator.mapping.cache.file%</argument>
3235
<argument type="service" id="cache.validator" />
36+
<tag name="kernel.cache_warmer" />
37+
</service>
38+
39+
<service id="validator.mapping.cache.symfony" class="Symfony\Component\Validator\Mapping\Cache\Psr6Cache" public="false">
40+
<argument type="service">
41+
<service class="Symfony\Component\Cache\Adapter\PhpArrayAdapter">
42+
<factory class="Symfony\Component\Cache\Adapter\PhpArrayAdapter" method="create" />
43+
<argument>%validator.mapping.cache.file%</argument>
44+
<argument type="service" id="cache.validator" />
45+
</service>
46+
</argument>
3347
</service>
3448

3549
<service id="validator.mapping.cache.doctrine.apc" class="Symfony\Component\Validator\Mapping\Cache\DoctrineCache" public="false">

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ protected static function getBundleDefaultConfig()
211211
'static_method' => array('loadValidatorMetadata'),
212212
'translation_domain' => 'validators',
213213
'strict_email' => false,
214-
'cache' => 'validator.mapping.cache.symfony',
215214
),
216215
'annotations' => array(
217216
'cache' => 'php_array',

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
),
5757
'validation' => array(
5858
'enabled' => true,
59-
'cache' => 'validator.mapping.cache.doctrine.apc',
6059
),
6160
'annotations' => array(
6261
'cache' => 'file',

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<framework:translator enabled="true" fallback="fr" logging="true">
3939
<framework:path>%kernel.root_dir%/Fixtures/translations</framework:path>
4040
</framework:translator>
41-
<framework:validation enabled="true" cache="validator.mapping.cache.doctrine.apc" />
41+
<framework:validation enabled="true" />
4242
<framework:annotations cache="file" debug="true" file-cache-dir="%kernel.cache_dir%/annotations" />
4343
<framework:serializer enabled="true" enable-annotations="true" name-converter="serializer.name_converter.camel_case_to_snake_case" />
4444
<framework:property-info />

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ framework:
4444
paths: ['%kernel.root_dir%/Fixtures/translations']
4545
validation:
4646
enabled: true
47-
cache: validator.mapping.cache.doctrine.apc
4847
annotations:
4948
cache: file
5049
debug: true

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ public function testValidation()
336336
$this->assertSame('addMethodMapping', $calls[4][0]);
337337
$this->assertSame(array('loadValidatorMetadata'), $calls[4][1]);
338338
$this->assertSame('setMetadataCache', $calls[5][0]);
339-
$this->assertEquals(array(new Reference('validator.mapping.cache.doctrine.apc')), $calls[5][1]);
339+
$this->assertEquals(array(new Reference('validator.mapping.cache.symfony')), $calls[5][1]);
340340
}
341341

342342
public function testValidationService()

src/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,7 @@ class XmlFileLoader extends FileLoader
3535
public function loadClassMetadata(ClassMetadata $metadata)
3636
{
3737
if (null === $this->classes) {
38-
// This method may throw an exception. Do not modify the class'
39-
// state before it completes
40-
$xml = $this->parseFile($this->file);
41-
42-
$this->classes = array();
43-
44-
foreach ($xml->namespace as $namespace) {
45-
$this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
46-
}
47-
48-
foreach ($xml->class as $class) {
49-
$this->classes[(string) $class['name']] = $class;
50-
}
38+
$this->loadClassesFromXml();
5139
}
5240

5341
if (isset($this->classes[$metadata->getClassName()])) {
@@ -61,6 +49,20 @@ public function loadClassMetadata(ClassMetadata $metadata)
6149
return false;
6250
}
6351

52+
/**
53+
* Return the names of the classes mapped in this file.
54+
*
55+
* @return array The classes names
56+
*/
57+
public function getClassesNames()
58+
{
59+
if (null === $this->classes) {
60+
$this->loadClassesFromXml();
61+
}
62+
63+
return array_keys($this->classes);
64+
}
65+
6466
/**
6567
* Parses a collection of "constraint" XML nodes.
6668
*
@@ -182,6 +184,26 @@ protected function parseFile($path)
182184
return simplexml_import_dom($dom);
183185
}
184186

187+
/**
188+
* Load the classes XML descriptions.
189+
*/
190+
private function loadClassesFromXml()
191+
{
192+
// This method may throw an exception. Do not modify the class'
193+
// state before it completes
194+
$xml = $this->parseFile($this->file);
195+
196+
$this->classes = array();
197+
198+
foreach ($xml->namespace as $namespace) {
199+
$this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
200+
}
201+
202+
foreach ($xml->class as $class) {
203+
$this->classes[(string) $class['name']] = $class;
204+
}
205+
}
206+
185207
/**
186208
* Loads the validation metadata from the given XML class description.
187209
*

src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,7 @@ class YamlFileLoader extends FileLoader
4242
public function loadClassMetadata(ClassMetadata $metadata)
4343
{
4444
if (null === $this->classes) {
45-
if (null === $this->yamlParser) {
46-
$this->yamlParser = new YamlParser();
47-
}
48-
49-
// This method may throw an exception. Do not modify the class'
50-
// state before it completes
51-
if (false === ($classes = $this->parseFile($this->file))) {
52-
return false;
53-
}
54-
55-
$this->classes = $classes;
56-
57-
if (isset($this->classes['namespaces'])) {
58-
foreach ($this->classes['namespaces'] as $alias => $namespace) {
59-
$this->addNamespaceAlias($alias, $namespace);
60-
}
61-
62-
unset($this->classes['namespaces']);
63-
}
45+
$this->loadClassesFromYaml();
6446
}
6547

6648
if (isset($this->classes[$metadata->getClassName()])) {
@@ -74,6 +56,20 @@ public function loadClassMetadata(ClassMetadata $metadata)
7456
return false;
7557
}
7658

59+
/**
60+
* Return the names of the classes mapped in this file.
61+
*
62+
* @return array The classes names
63+
*/
64+
public function getClassesNames()
65+
{
66+
if (null === $this->classes) {
67+
$this->loadClassesFromYaml();
68+
}
69+
70+
return array_keys($this->classes);
71+
}
72+
7773
/**
7874
* Parses a collection of YAML nodes.
7975
*
@@ -137,6 +133,32 @@ private function parseFile($path)
137133
return $classes;
138134
}
139135

136+
/**
137+
* Load the classes YAML descriptions.
138+
*/
139+
private function loadClassesFromYaml()
140+
{
141+
if (null === $this->yamlParser) {
142+
$this->yamlParser = new YamlParser();
143+
}
144+
145+
// This method may throw an exception. Do not modify the class'
146+
// state before it completes
147+
if (false === ($classes = $this->parseFile($this->file))) {
148+
return false;
149+
}
150+
151+
$this->classes = $classes;
152+
153+
if (isset($this->classes['namespaces'])) {
154+
foreach ($this->classes['namespaces'] as $alias => $namespace) {
155+
$this->addNamespaceAlias($alias, $namespace);
156+
}
157+
158+
unset($this->classes['namespaces']);
159+
}
160+
}
161+
140162
/**
141163
* Loads the validation metadata from the given YAML class description.
142164
*

0 commit comments

Comments
 (0)