8000 Metadata aware PropertyAccessor support for FrameworkBundle · symfony/symfony@fe9b784 · GitHub
[go: up one dir, main page]

Skip to content

Commit fe9b784

Browse files
committed
Metadata aware PropertyAccessor support for FrameworkBundle
1 parent 2f2ad49 commit fe9b784

File tree

13 files changed

+119
-99
lines changed

13 files changed

+119
-99
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,15 @@ private function addPropertyAccessSection(ArrayNodeDefinition $rootNode)
786786
->children()
787787
->booleanNode('magic_call')->defaultFalse()->end()
788788
->booleanNode('throw_exception_on_invalid_index')->defaultFalse()->end()
789+
->booleanNode('enable_annotations')->defaultFalse()->end()
790+
->arrayNode('mapping')
791+
->addDefaultsIfNotSet()
792+
->fixXmlConfig('path')
793+
->children()
794+
->arrayNode('paths')
795+
->prototype('scalar')->end()
796+
->end()
797+
->end()
789798
->end()
790799
->end()
791800
->end()

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

Lines changed: 75 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ public function load(array $configs, ContainerBuilder $container)
295295
$this->registerDebugConfiguration($config['php_errors'], $container, $loader);
296296
$this->registerRouterConfiguration($config['router'], $container, $loader);
297297
$this->registerAnnotationsConfiguration($config['annotations'], $container, $loader);
298-
$this->registerPropertyAccessConfiguration($config['property_access'], $container);
298+
$this->registerPropertyAccessConfiguration($config['property_access'], $container, $loader);
299299

300300
if ($this->isConfigEnabled($container, $config['serializer'])) {
301301
$this->registerSerializerConfiguration($config['serializer'], $container, $loader);
@@ -1309,6 +1309,35 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
13091309
}
13101310
}
13111311

1312+
/**
1313+
* @param ContainerBuilder $container
1314+
* @param array $config
1315+
* @param $component
1316+
* @param $fileRecorder
1317+
*/
1318+
private function registerComponentMapping(ContainerBuilder $container, array $config, $component, &$fileRecorder)
1319+
{
1320+
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
1321+
$dirname = $bundle['path'];
1322+
1323+
if (
1324+
$container->fileExists($file = $dirname.'/Resources/config/'.$component.'.yaml', false) ||
1325+
$container->fileExists($file = $dirname.'/Resources/config/'.$component.'.yml', false)
1326+
) {
1327+
$fileRecorder('yml', $file);
1328+
}
1329+
1330+
if ($container->fileExists($file = $dirname.'/Resources/config/'.$component.'.xml', false)) {
1331+
$fileRecorder('xml', $file);
1332+
}
1333+
1334+
if ($container->fileExists($dir = $dirname.'/Resources/config/'.$component, '/^$/')) {
1335+
$this->registerMappingFilesFromDir($dir, $fileRecorder);
1336+
}
1337+
}
1338+
$this->registerMappingFilesFromConfig($container, $config, $fileRecorder);
1339+
}
1340+
13121341
/**
13131342
* Loads the validator configuration.
13141343
*
@@ -1337,7 +1366,17 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
13371366
$container->setParameter('validator.translation_domain', $config['translation_domain']);
13381367

13391368
$files = array('xml' => array(), 'yml' => array());
1340-
$this->registerValidatorMapping($container, $config, $files);
1369+
1370+
$fileRecorder = function ($extension, $path) use (&$files) {
1371+
$files['yaml' === $extension ? 'yml' : $extension][] = $path;
1372+
};
1373+
1374+
if (interface_exists('Symfony\Component\Form\FormInterface')) {
1375+
$reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface');
1376+
$fileRecorder('xml', dirname($reflClass->getFileName()).'/Resources/config/validation.xml');
1377+
}
1378+
1379+
$this->registerComponentMapping($container, $config, 'validation', $fileRecorder);
13411380

13421381
if (!empty($files['xml'])) {
13431382
$validatorBuilder->addMethodCall('addXmlMappings', array($files['xml']));
@@ -1363,7 +1402,6 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
13631402
$validatorBuilder->addMethodCall('addMethodMapping', array($methodName));
13641403
}
13651404
}
1366-
13671405
if (isset($config['cache']) && $config['cache']) {
13681406
$container->setParameter(
13691407
'validator.mapping.cache.prefix',
@@ -1376,39 +1414,6 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
13761414
}
13771415
}
13781416

1379-
private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files)
1380-
{
1381-
$fileRecorder = function ($extension, $path) use (&$files) {
1382-
$files['yaml' === $extension ? 'yml' : $extension][] = $path;
1383-
};
1384-
1385-
if (interface_exists('Symfony\Component\Form\FormInterface')) {
1386-
$reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface');
1387-
$fileRecorder('xml', dirname($reflClass->getFileName()).'/Resources/config/validation.xml');
1388-
}
1389-
1390-
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
1391-
$dirname = $bundle['path'];
1392-
1393-
if (
1394-
$container->fileExists($file = $dirname.'/Resources/config/validation.yaml', false) ||
1395-
$container->fileExists($file = $dirname.'/Resources/config/validation.yml', false)
1396-
) {
1397-
$fileRecorder('yml', $file);
1398-
}
1399-
1400-
if ($container->fileExists($file = $dirname.'/Resources/config/validation.xml', false)) {
1401-
$fileRecorder('xml', $file);
1402-
}
1403-
1404-
if ($container->fileExists($dir = $dirname.'/Resources/config/validation', '/^$/')) {
1405-
$this->registerMappingFilesFromDir($dir, $fileRecorder);
1406-
}
1407-
}
1408-
1409-
$this->registerMappingFilesFromConfig($container, $config, $fileRecorder);
1410-
}
1411-
14121417
private function registerMappingFilesFromDir($dir, callable $fileRecorder)
14131418
{
14141419
foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/') as $file) {
@@ -1494,12 +1499,45 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde
14941499
}
14951500
}
14961501

1497-
private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container)
1502+
private function registerPropertyAccessConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
14981503
{
1504+
$loader->load('property_access.xml');
1505+
1506+
$chainLoader = $container->getDefinition('property_access.mapping.chain_loader');
1507+
1508+
$serializerLoaders = array();
1509+
if (isset($config['enable_annotations']) && $config['enable_annotations']) {
1510+
if (!$this->annotationsConfigEnabled) {
1511+
throw new \LogicException('"enable_annotations" on property access cannot be set as Annotations support is disabled.');
1512+
}
1513+
1514+
$annotationLoader = new Definition(
1515+
'Symfony\Component\PropertyAccess\Mapping\Loader\AnnotationLoader',
1516+
array(new Reference('annotation_reader'))
1517+
);
1518+
$annotationLoader->setPublic(false);
1519+
1520+
$serializerLoaders[] = $annotationLoader;
1521+
}
1522+
1523+
$fileRecorder = function ($extension, $path) use (&$serializerLoaders) {
1524+
$definition = new Definition(in_array($extension, array('yaml', 'yml')) ? 'Symfony\Component\PropertyAccess\Mapping\Loader\YamlFileLoader' : 'Symfony\Component\PropertyAccess\Mapping\Loader\XmlFileLoader', array($path));
1525+
$definition->setPublic(false);
1526+
$serializerLoaders[] = $definition;
1527+
};
1528+
1529+
$this->registerComponentMapping($container, $config, 'property_accessor', $fileRecorder);
1530+
1531+
$chainLoader->replaceArgument(0, $serializerLoaders);
1532+
1533+
$metadataLoader = $container->getDefinition('property_access.mapping.class_metadata_factory')
1534+
->replaceArgument(0, $chainLoader);
1535+
14991536
$container
15001537
->getDefinition('property_accessor')
15011538
->replaceArgument(0, $config['magic_call'])
15021539
->replaceArgument(1, $config['throw_exception_on_invalid_index'])
1540+
->replaceArgument(3, $metadataLoader)
15031541
;
15041542
}
15051543

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
<tag name="cache.pool" />
2828
</service>
2929

30+
<service id="cache.property_access" parent="cache.system" public="false">
31+
<tag name="cache.pool" />
32+
</service>
33+
3034
<service id="cache.adapter.system" class="Symfony\Component\Cache\Adapter\AdapterInterface" abstract="true">
3135
<factory class="Symfony\Component\Cache\Adapter\AbstractAdapter" method="createSystemCache" />
3236
<tag name="cache.pool" clearer="cache.system_clearer" />

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,21 @@
77
<services>
88
<defaults public="false" />
99

10+
<!-- Loader -->
11+
<service id="property_access.mapping.chain_loader" class="Symfony\Component\PropertyAccess\Mapping\Loader\LoaderChain" public="false">
12+
<argument type="collection" />
13+
</service>
14+
15+
<!-- Class Metadata Factory -->
16+
<service id="property_access.mapping.class_metadata_factory" class="Symfony\Component\PropertyAccess\Mapping\Factory\LazyLoadingMetadataFactory" public="false">
17+
<argument type="service" id="property_access.mapping.chain_loader" />
18+
</service>
19+
1020
<service id="property_accessor" class="Symfony\Component\PropertyAccess\PropertyAccessor">
1121
<argument /> <!-- magicCall, set by the extension -->
1222
<argument /> <!-- throwExceptionOnInvalidIndex, set by the extension -->
1323
<argument type="service" id="cache.property_access" on-invalid="ignore" />
24+
<argument />
1425
</service>
1526
<service id="Symfony\Component\PropertyAccess\PropertyAccessorInterface" alias="property_accessor" />
1627
</services>

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,12 @@
214214
</xsd:complexType>
215215

216216
<xsd:complexType name="property_access">
217+
<xsd:choice minOccurs="0" maxOccurs="unbounded">
218+
<xsd:element name="mapping" type="file_mapping" />
219+
</xsd:choice>
217220
<xsd:attribute name="magic-call" type="xsd:boolean" />
218221
<xsd:attribute name="throw-exception-on-invalid-index" type="xsd:boolean" />
222+
<xsd:attribute name="enable-annotations" type="xsd:boolean" />
219223
</xsd:complexType>
220224

221225
<xsd:complexType name="serializer">

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,10 @@ protected static function getBundleDefaultConfig()
283283
'property_access' => array(
284284
'magic_call' => false,
285285
'throw_exception_on_invalid_index' => false,
286+
'enable_annotations' => false,
287+
'mapping' => array(
288+
'paths' => array(),
289+
),
286290
),
287291
'property_info' => array(
288292
'enabled' => false,

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@
6464
'debug' => true,
6565
'file_cache_dir' => '%kernel.cache_dir%/annotations',
6666
),
67+
'property_access' => array(
68+
'magic_call' => false,
69+
'throw_exception_on_invalid_index' => false,
70+
'enable_annotations' => true,
71+
),
6772
'serializer' => array(
6873
'enabled' => true,
6974
'enable_annotations' => true,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
'property_access' => array(
55
'magic_call' => true,
66
'throw_exception_on_invalid_index' => true,
7+
'enable_annotations' => true,
78
),
89
));

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
88

99
<framework:config>
10-
<framework:property-access magic-call="true" throw-exception-on-invalid-index="true" />
10+
<framework:property-access magic-call="true" throw-exception-on-invalid-index="true" enable-annotations="false" />
1111
</framework:config>
1212
</container>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ framework:
5353
enabled: true
5454
enable_annotations: true
5555
name_converter: serializer.name_converter.camel_case_to_snake_case
56+
property_access:
57+
enable_annotations: true
58+
magic_call: false
59+
throw_exception_on_invalid_index: false
5660
property_info: ~
5761
ide: file%%link%%format
5862
request:

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ framework:
22
property_access:
33
magic_call: true
44
throw_exception_on_invalid_index: true
5+
enable_annotations: false

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

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
1818
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
1919
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
20-
use Symfony\Component\Cache\Adapter\AdapterInterface;
2120
use Symfony\Component\Cache\Adapter\ApcuAdapter;
22-
use Symfony\Component\Cache\Adapter\ArrayAdapter;
2321
use Symfony\Component\Cache\Adapter\ChainAdapter;
2422
use Symfony\Component\Cache\Adapter\DoctrineAdapter;
2523
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
@@ -32,7 +30,6 @@
3230
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
3331
use Symfony\Component\DependencyInjection\Reference;
3432
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
35-
use Symfony\Component\PropertyAccess\PropertyAccessor;
3633
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
3734
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
3835
use Symfony\Component\Serializer\Serializer;
@@ -81,32 +78,6 @@ public function testPropertyAccessWithOverriddenValues()
8178
$this->assertTrue($def->getArgument(1));
8279
}
8380

84-
public function testPropertyAccessCache()
85-
{
86-
$container = $this->createContainerFromFile('property_accessor');
87-
88-
if (!method_exists(PropertyAccessor::class, 'createCache')) {
89-
return $this->assertFalse($container->hasDefinition('cache.property_access'));
90-
}
91-
92-
$cache = $container->getDefinition('cache.property_access');
93-
$this->assertSame(array(PropertyAccessor::class, 'createCache'), $cache->getFactory(), 'PropertyAccessor::createCache() should be used in non-debug mode');
94-
$this->assertSame(AdapterInterface::class, $cache->getClass());
95-
}
96-
97-
public function testPropertyAccessCacheWithDebug()
98-
{
99-
$container = $this->createContainerFromFile('property_accessor', array('kernel.debug' => true));
100-
101-
if (!method_exists(PropertyAccessor::class, 'createCache')) {
102-
return $this->assertFalse($container->hasDefinition('cache.property_access'));
103-
}
104-
105-
$cache = $container->getDefinition('cache.property_access');
106-
$this->assertNull($cache->getFactory());
107-
$this->assertSame(ArrayAdapter::class, $cache->getClass(), 'ArrayAdapter should be used in debug mode');
108-
}
109-
11081
/**
11182
* @expectedException \LogicException
11283
* @expectedExceptionMessage CSRF protection needs sessions to be enabled.

src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -934,38 +934,6 @@ private function getPropertyPath($propertyPath)
934934
return $this->propertyPathCache[$propertyPath] = $propertyPathInstance;
935935
}
936936

937-
/**
938-
* Creates the APCu adapter if applicable.
939-
*
940-
* @param string $namespace
941-
* @param int $defaultLifetime
942-
* @param string $version
943-
* @param LoggerInterface|null $logger
944-
*
945-
* @return AdapterInterface
946-
*
947-
* @throws RuntimeException When the Cache Component isn't available
948-
*/
949-
public static function createCache($namespace, $defaultLifetime, $version, LoggerInterface $logger = null)
950-
{
951-
if (!class_exists('Symfony\Component\Cache\Adapter\ApcuAdapter')) {
952-
throw new \RuntimeException(sprintf('The Symfony Cache component must be installed to use %s().', __METHOD__));
953-
}
954-
955-
if (!ApcuAdapter::isSupported()) {
956-
return new NullAdapter();
957-
}
958-
959-
$apcu = new ApcuAdapter($namespace, $defaultLifetime / 5, $version);
960-
if ('cli' === \PHP_SAPI && !ini_get('apc.enable_cli')) {
961-
$apcu->setLogger(new NullLogger());
962-
} elseif (null !== $logger) {
963-
$apcu->setLogger($logger);
964-
}
965-
966-
return $apcu;
967-
}
968-
969937
/**
970938
* Returns metadata associated with the property if it exists.
971939
*

0 commit comments

Comments
 (0)
0