diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index da650439d6..d22844d552 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -35,6 +35,8 @@ CHANGELOG `server:status` console commands have been moved to a dedicated bundle. Require `symfony/web-server-bundle` in your composer.json and register `Symfony\Bundle\WebServerBundle\WebServerBundle` in your AppKernel to use them. + * Added `framework.serializer.mapping` config option allowing to define custom + serialization mapping files and directories 3.2.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index ae2250e3d4..c465bab4bd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -686,6 +686,15 @@ class Configuration implements ConfigurationInterface ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() ->scalarNode('cache')->end() ->scalarNode('name_converter')->end() + ->arrayNode('mapping') + ->addDefaultsIfNotSet() + ->fixXmlConfig('path') + ->children() + ->arrayNode('paths') + ->prototype('scalar')->end() + ->end() + ->end() + ->end() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 17a613b70c..2cc0c01e83 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -986,8 +986,7 @@ class FrameworkExtension extends Extension $container->setParameter('validator.translation_domain', $config['translation_domain']); $files = array('xml' => array(), 'yml' => array()); - $this->getValidatorMappingFiles($container, $files); - $this->getValidatorMappingFilesFromConfig($container, $config, $files); + $this->registerValidatorMapping($container, $config, $files); if (!empty($files['xml'])) { $validatorBuilder->addMethodCall('addXmlMappings', array($files['xml'])); @@ -1028,51 +1027,54 @@ class FrameworkExtension extends Extension } } - private function getValidatorMappingFiles(ContainerBuilder $container, array &$files) + private function registerValidatorMapping(ContainerBuilder $container, array $config, array &$files) { + $fileRecorder = function ($extension, $path) use (&$files) { + $files['yaml' === $extension ? 'yml' : $extension][] = $path; + }; + if (interface_exists('Symfony\Component\Form\FormInterface')) { $reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface'); - $files['xml'][] = dirname($reflClass->getFileName()).'/Resources/config/validation.xml'; + $fileRecorder('xml', dirname($reflClass->getFileName()).'/Resources/config/validation.xml'); } foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { $dirname = $bundle['path']; if ($container->fileExists($file = $dirname.'/Resources/config/validation.yml', false)) { - $files['yml'][] = $file; + $fileRecorder('yml', $file); } if ($container->fileExists($file = $dirname.'/Resources/config/validation.xml', false)) { - $files['xml'][] = $file; + $fileRecorder('xml', $file); } if ($container->fileExists($dir = $dirname.'/Resources/config/validation', '/^$/')) { - $this->getValidatorMappingFilesFromDir($dir, $files); + $this->registerMappingFilesFromDir($dir, $fileRecorder); } } + + $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); } - private function getValidatorMappingFilesFromDir($dir, array &$files) + private function registerMappingFilesFromDir($dir, callable $fileRecorder) { foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/') as $file) { - $extension = $file->getExtension(); - $files['yaml' === $extension ? 'yml' : $extension][] = $file->getRealpath(); + $fileRecorder($file->getExtension(), $file->getRealPath()); } } - private function getValidatorMappingFilesFromConfig(ContainerBuilder $container, array $config, array &$files) + private function registerMappingFilesFromConfig(ContainerBuilder $container, array $config, callable $fileRecorder) { foreach ($config['mapping']['paths'] as $path) { if (is_dir($path)) { - $this->getValidatorMappingFilesFromDir($path, $files); + $this->registerMappingFilesFromDir($path, $fileRecorder); $container->addResource(new DirectoryResource($path, '/^$/')); } elseif ($container->fileExists($path, false)) { - if (preg_match('/\.(xml|ya?ml)$/', $path, $matches)) { - $extension = $matches[1]; - $files['yaml' === $extension ? 'yml' : $extension][] = $path; - } else { + if (!preg_match('/\.(xml|ya?ml)$/', $path, $matches)) { throw new \RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path)); } + $fileRecorder($matches[1], $path); } else { throw new \RuntimeException(sprintf('Could not open file or directory "%s".', $path)); } @@ -1230,39 +1232,30 @@ class FrameworkExtension extends Extension $serializerLoaders[] = $annotationLoader; } + $fileRecorder = function ($extension, $path) use (&$serializerLoaders) { + $definition = new Definition(in_array($extension, array('yaml', 'yml')) ? 'Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader' : 'Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($path)); + $definition->setPublic(false); + $serializerLoaders[] = $definition; + }; + foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { $dirname = $bundle['path']; if ($container->fileExists($file = $dirname.'/Resources/config/serialization.xml', false)) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file)); - $definition->setPublic(false); - - $serializerLoaders[] = $definition; + $fileRecorder('xml', $file); } if ($container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false)) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file)); - $definition->setPublic(false); - - $serializerLoaders[] = $definition; + $fileRecorder('yml', $file); } if ($container->fileExists($dir = $dirname.'/Resources/config/serialization')) { - foreach (Finder::create()->followLinks()->files()->in($dir)->name('*.xml') as $file) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader', array($file->getPathname())); - $definition->setPublic(false); - - $serializerLoaders[] = $definition; - } - foreach (Finder::create()->followLinks()->files()->in($dir)->name('*.yml') as $file) { - $definition = new Definition('Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader', array($file->getPathname())); - $definition->setPublic(false); - - $serializerLoaders[] = $definition; - } + $this->registerMappingFilesFromDir($dir, $fileRecorder); } } + $this->registerMappingFilesFromConfig($container, $config, $fileRecorder); + $chainLoader->replaceArgument(0, $serializerLoaders); $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 805068be5f..2ec8540ef2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -176,7 +176,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -204,6 +204,9 @@ + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 940b6acad1..3d101d030a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -226,6 +226,7 @@ class ConfigurationTest extends TestCase 'serializer' => array( 'enabled' => !class_exists(FullStack::class), 'enable_annotations' => !class_exists(FullStack::class), + 'mapping' => array('paths' => array()), ), 'property_access' => array( 'magic_call' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serialization.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/files/foo.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php new file mode 100644 index 0000000000..4e437bf4e8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_mapping.php @@ -0,0 +1,15 @@ +loadFromExtension('framework', array( + 'annotations' => array('enabled' => true), + 'serializer' => array( + 'enable_annotations' => true, + 'mapping' => array( + 'paths' => array( + '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files', + '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml', + '%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml', + ), + ), + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml new file mode 100644 index 0000000000..9fec09f0db --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_mapping.xml @@ -0,0 +1,17 @@ + + + + + + + + + %kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files + %kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml + %kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml new file mode 100644 index 0000000000..b977dc89be --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_mapping.yml @@ -0,0 +1,10 @@ +framework: + annotations: + enabled: true + serializer: + enable_annotations: true + mapping: + paths: + - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/files" + - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yml" + - "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/serializer_mapping/serialization.yaml" diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 64423bda88..1d5c2c6804 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -27,10 +27,12 @@ use Symfony\Component\Cache\Adapter\ProxyAdapter; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; @@ -799,6 +801,28 @@ abstract class FrameworkExtensionTest extends TestCase $this->assertEquals(new Reference('foo'), $cache); } + public function testSerializerMapping() + { + $container = $this->createContainerFromFile('serializer_mapping', array('kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle', 'parent' => null)))); + $configDir = __DIR__.'/Fixtures/TestBundle/Resources/config'; + $expectedLoaders = array( + new Definition(AnnotationLoader::class, array(new Reference('annotation_reader'))), + new Definition(XmlFileLoader::class, array($configDir.'/serialization.xml')), + new Definition(YamlFileLoader::class, array($configDir.'/serialization.yml')), + new Definition(XmlFileLoader::class, array($configDir.'/serializer_mapping/files/foo.xml')), + new Definition(YamlFileLoader::class, array($configDir.'/serializer_mapping/files/foo.yml')), + new Definition(YamlFileLoader::class, array($configDir.'/serializer_mapping/serialization.yml')), + new Definition(YamlFileLoader::class, array($configDir.'/serializer_mapping/serialization.yaml')), + ); + + foreach ($expectedLoaders as $definition) { + $definition->setPublic(false); + } + + $loaders = $container->getDefinition('serializer.mapping.chain_loader')->getArgument(0); + $this->assertEquals(sort($expectedLoaders), sort($loaders)); + } + public function testAssetHelperWhenAssetsAreEnabled() { $container = $this->createContainerFromFile('full');