[FrameworkBundle] Configurable paths for validation files

This commit is contained in:
David Wolter 2017-01-23 15:03:11 +01:00
parent 60d7d437b5
commit d696cfb04c
13 changed files with 114 additions and 22 deletions

View File

@ -12,6 +12,7 @@ CHANGELOG
is disabled.
* Added `GlobalVariables::getToken()`
* Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass`. Use `Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass` instead.
* Added configurable paths for validation files
3.2.0
-----

View File

@ -635,6 +635,15 @@ class Configuration implements ConfigurationInterface
->end()
->scalarNode('translation_domain')->defaultValue('validators')->end()
->booleanNode('strict_email')->defaultFalse()->end()
->arrayNode('mapping')
->addDefaultsIfNotSet()
->fixXmlConfig('path')
->children()
->arrayNode('paths')
->prototype('scalar')->end()
->end()
->end()
->end()
->end()
->end()
->end()

View File

@ -947,13 +947,16 @@ class FrameworkExtension extends Extension
$container->setParameter('validator.translation_domain', $config['translation_domain']);
list($xmlMappings, $yamlMappings) = $this->getValidatorMappingFiles($container);
if (count($xmlMappings) > 0) {
$validatorBuilder->addMethodCall('addXmlMappings', array($xmlMappings));
$files = array('xml' => array(), 'yml' => array());
$this->getValidatorMappingFiles($container, $files);
$this->getValidatorMappingFilesFromConfig($config, $files);
if (!empty($files['xml'])) {
$validatorBuilder->addMethodCall('addXmlMappings', array($files['xml']));
}
if (count($yamlMappings) > 0) {
$validatorBuilder->addMethodCall('addYamlMappings', array($yamlMappings));
if (!empty($files['yml'])) {
$validatorBuilder->addMethodCall('addYamlMappings', array($files['yml']));
}
$definition = $container->findDefinition('validator.email');
@ -987,41 +990,58 @@ class FrameworkExtension extends Extension
}
}
private function getValidatorMappingFiles(ContainerBuilder $container)
private function getValidatorMappingFiles(ContainerBuilder $container, array &$files)
{
$files = array(array(), array());
if (interface_exists('Symfony\Component\Form\FormInterface')) {
$reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface');
$files[0][] = dirname($reflClass->getFileName()).'/Resources/config/validation.xml';
$container->addResource(new FileResource($files[0][0]));
$files['xml'][] = $file = dirname($reflClass->getFileName()).'/Resources/config/validation.xml';
$container->addResource(new FileResource($file));
}
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
$dirname = $bundle['path'];
if (is_file($file = $dirname.'/Resources/config/validation.xml')) {
$files[0][] = $file;
if (is_file($file = $dirname.'/Resources/config/validation.yml')) {
$files['yml'][] = $file;
$container->addResource(new FileResource($file));
}
if (is_file($file = $dirname.'/Resources/config/validation.yml')) {
$files[1][] = $file;
if (is_file($file = $dirname.'/Resources/config/validation.xml')) {
$files['xml'][] = $file;
$container->addResource(new FileResource($file));
}
if (is_dir($dir = $dirname.'/Resources/config/validation')) {
foreach (Finder::create()->followLinks()->files()->in($dir)->name('*.xml') as $file) {
$files[0][] = $file->getPathname();
}
foreach (Finder::create()->followLinks()->files()->in($dir)->name('*.yml') as $file) {
$files[1][] = $file->getPathname();
}
$this->getValidatorMappingFilesFromDir($dir, $files);
$container->addResource(new DirectoryResource($dir));
}
}
}
return $files;
private function getValidatorMappingFilesFromDir($dir, array &$files)
{
foreach (Finder::create()->followLinks()->files()->in($dir)->name('/\.(xml|ya?ml)$/') as $file) {
$extension = $file->getExtension();
$files['yaml' === $extension ? 'yml' : $extension][] = $file->getRealpath();
}
}
private function getValidatorMappingFilesFromConfig(array $config, array &$files)
{
foreach ($config['mapping']['paths'] as $path) {
if (is_dir($path)) {
$this->getValidatorMappingFilesFromDir($path, $files);
} elseif (is_file($path)) {
if (preg_match('/\.(xml|ya?ml)$/', $path, $matches)) {
$extension = $matches[1];
$files['yaml' === $extension ? 'yml' : $extension][] = $path;
} else {
throw new \RuntimeException(sprintf('Unsupported mapping type in "%s", supported types are XML & Yaml.', $path));
}
} else {
throw new \RuntimeException(sprintf('Could not open file or directory "%s".', $path));
}
}
}
private function registerAnnotationsConfiguration(array $config, ContainerBuilder $container, $loader)

View File

@ -176,6 +176,7 @@
<xsd:complexType name="validation">
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="static-method" type="xsd:string" />
<xsd:element name="mapping" type="validation_mapping" />
</xsd:choice>
<xsd:attribute name="enabled" type="xsd:boolean" />
@ -184,6 +185,12 @@
<xsd:attribute name="static-method" type="xsd:boolean" />
</xsd:complexType>
<xsd:complexType name="validation_mapping">
<xsd:sequence>
<xsd:element name="path" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="annotations">
<xsd:attribute name="cache" type="xsd:string" />
<xsd:attribute name="debug" type="xsd:string" />

View File

@ -212,6 +212,9 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase
'static_method' => array('loadValidatorMetadata'),
'translation_domain' => 'validators',
'strict_email' => false,
'mapping' => array(
'paths' => array(),
),
),
'annotations' => array(
'cache' => 'php_array',

View File

@ -0,0 +1,13 @@
<?php
$container->loadFromExtension('framework', array(
'validation' => array(
'mapping' => array(
'paths' => array(
'%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/files',
'%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml',
'%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml',
),
),
),
));

View File

@ -0,0 +1,16 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony">
<framework:config>
<framework:validation>
<framework:mapping>
<framework:path>%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/files</framework:path>
<framework:path>%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml</framework:path>
<framework:path>%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml</framework:path>
</framework:mapping>
</framework:validation>
</framework:config>
</container>

View File

@ -0,0 +1,7 @@
framework:
validation:
mapping:
paths:
- "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/files"
- "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yml"
- "%kernel.root_dir%/Fixtures/TestBundle/Resources/config/validation_mapping/validation.yaml"

View File

@ -584,6 +584,22 @@ abstract class FrameworkExtensionTest extends TestCase
// no cache, no annotations, no static methods
}
public function testValidationMapping()
{
$container = $this->createContainerFromFile('validation_mapping');
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
$this->assertSame('addXmlMappings', $calls[3][0]);
$this->assertCount(2, $calls[3][1][0]);
$this->assertSame('addYamlMappings', $calls[4][0]);
$this->assertCount(3, $calls[4][1][0]);
$this->assertContains('foo.yml', $calls[4][1][0][0]);
$this->assertContains('validation.yml', $calls[4][1][0][1]);
$this->assertContains('validation.yaml', $calls[4][1][0][2]);
}
public function testFormsCanBeEnabledWithoutCsrfProtection()
{
$container = $this->createContainerFromFile('form_no_csrf');