Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 41a9e8f

Browse filesBrowse files
committed
[FrameworkBundle] Introduce a cache warmer for Validator based on PhpArrayAdapter
1 parent 983b560 commit 41a9e8f
Copy full SHA for 41a9e8f

File tree

Expand file treeCollapse file tree

12 files changed

+237
-70
lines changed
Filter options
Expand file treeCollapse file tree

12 files changed

+237
-70
lines changed
+114Lines 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 <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 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 <galopintitouan@gmail.com>
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+
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+1-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+5-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
+15-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
+1-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+1-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Mapping/Loader/XmlFileLoader.php
+35-13Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php
+41-19Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.