feature #19086 [FrameworkBundle] add "mapping" configuration key at validation secti… (davewwww)
This PR was merged into the 3.3-dev branch. Discussion ---------- [FrameworkBundle] add "mapping" configuration key at validation secti… | Q | A | | --- | --- | | Bug fix? | no | | New feature? | yes | | BC breaks? | no | | Deprecations? | no | | Tests pass? | yes | | Fixed tickets | #15655 | | License | MIT | | Doc PR | https://github.com/symfony/symfony-docs/pull/7407 | This feature allows you, to define additional validation files or directories which are not in the 'Bundle*/Resources/config/' directory. ``` yaml #config.yml framework: validation: mapping: paths: - "path/to/file/validation.yml" - "path/to/file/validation.xml" - "path/to/another/directory" ``` Commits -------d696cfb04c
[FrameworkBundle] Configurable paths for validation files60d7d437b5
fix merge61475b5596
Merge branch '3.2'ba41e706ad
Merge branch '3.1' into 3.24268abacf4
Merge branch '2.8' into 3.13faf655638
Merge branch '2.7' into 2.8e95fc09b3c
fix getMock usage482828ce29
fix mergeed5eb6db54
bug #21372 [DependencyInjection] Fixed variadic method parameter in autowired classes (brainexe)a7f63de414
[DependencyInjection] Fixed variadic method parameter in autowired classes9ef427150c
minor #21371 [Validator] update German translation (xabbuh)f920e61d35
update German translation41c72ab909
minor #21335 [Validator] Improved error message for missing upload_tmp_dir (Breuls)afbf22746a
[Validator] Improved error message for missing upload_tmp_dir
This commit is contained in:
commit
3697e1e154
@ -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
|
||||
-----
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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" />
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
@ -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>
|
@ -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"
|
@ -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');
|
||||
|
@ -1,11 +1,9 @@
|
||||
alias_1
|
||||
~~~~~~~
|
||||
### alias_1
|
||||
|
||||
- Service: `service_1`
|
||||
- Public: yes
|
||||
|
||||
service_1
|
||||
~~~~~~~~~
|
||||
### service_1
|
||||
|
||||
- Class: `Full\Qualified\Class1`
|
||||
- Public: yes
|
||||
|
@ -1,11 +1,9 @@
|
||||
alias_2
|
||||
~~~~~~~
|
||||
### alias_2
|
||||
|
||||
- Service: `service_2`
|
||||
- Public: no
|
||||
|
||||
service_2
|
||||
~~~~~~~~~
|
||||
### service_2
|
||||
|
||||
- Class: `Full\Qualified\Class2`
|
||||
- Public: no
|
||||
|
@ -4,8 +4,7 @@ Public services
|
||||
Definitions
|
||||
-----------
|
||||
|
||||
definition_1
|
||||
~~~~~~~~~~~~
|
||||
### definition_1
|
||||
|
||||
- Class: `Full\Qualified\Class1`
|
||||
- Public: yes
|
||||
@ -22,14 +21,12 @@ definition_1
|
||||
Aliases
|
||||
-------
|
||||
|
||||
alias_1
|
||||
~~~~~~~
|
||||
### alias_1
|
||||
|
||||
- Service: `service_1`
|
||||
- Public: yes
|
||||
|
||||
alias_2
|
||||
~~~~~~~
|
||||
### alias_2
|
||||
|
||||
- Service: `service_2`
|
||||
- Public: no
|
||||
|
@ -21,15 +21,20 @@ class ExtensionPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->setParameter('kernel.debug', false);
|
||||
$container->setParameter('kernel.root_dir', __DIR__);
|
||||
|
||||
$container->register('twig.app_variable', '\Symfony\Bridge\Twig\AppVariable');
|
||||
$container->register('templating', '\Symfony\Bundle\TwigBundle\TwigEngine');
|
||||
$container->register('twig.extension.yaml');
|
||||
$container->register('twig.extension.debug.stopwatch');
|
||||
$container->register('twig.extension.expression');
|
||||
|
||||
$nativeTwigLoader = new Definition('\Twig_Loader_Filesystem');
|
||||
$nativeTwigLoader->addMethodCall('addPath', array());
|
||||
$container->setDefinition('twig.loader.native_filesystem', $nativeTwigLoader);
|
||||
|
||||
$filesystemLoader = new Definition('\Symfony\Bundle\TwigBundle\Loader\FilesystemLoader');
|
||||
$filesystemLoader->setArguments(array(null, null, null));
|
||||
$filesystemLoader->addMethodCall('addPath', array());
|
||||
$container->setDefinition('twig.loader.filesystem', $filesystemLoader);
|
||||
|
||||
|
@ -255,7 +255,7 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
// assertEquals() does not like NAN values.
|
||||
$this->assertEquals($array[$i][0], 'float');
|
||||
$this->assertNan($array[$i++][1]);
|
||||
$this->assertTrue(is_nan($array[$i++][1]));
|
||||
}
|
||||
|
||||
public function testRecursionInArguments()
|
||||
|
@ -428,10 +428,11 @@ class AutowirePass implements CompilerPassInterface
|
||||
$class = false;
|
||||
}
|
||||
|
||||
$isVariadic = method_exists($parameter, 'isVariadic') && $parameter->isVariadic();
|
||||
$methodArgumentsMetadata[] = array(
|
||||
'class' => $class,
|
||||
'isOptional' => $parameter->isOptional(),
|
||||
'defaultValue' => $parameter->isOptional() ? $parameter->getDefaultValue() : null,
|
||||
'defaultValue' => ($parameter->isOptional() && !$isVariadic) ? $parameter->getDefaultValue() : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
||||
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
@ -35,6 +36,23 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('foo', (string) $container->getDefinition('bar')->getArgument(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 5.6
|
||||
*/
|
||||
public function testProcessVariadic()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('foo', Foo::class);
|
||||
$definition = $container->register('fooVariadic', FooVariadic::class);
|
||||
$definition->setAutowired(true);
|
||||
|
||||
$pass = new AutowirePass();
|
||||
$pass->process($container);
|
||||
|
||||
$this->assertCount(1, $container->getDefinition('fooVariadic')->getArguments());
|
||||
$this->assertEquals('foo', (string) $container->getDefinition('fooVariadic')->getArgument(0));
|
||||
}
|
||||
|
||||
public function testProcessAutowireParent()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\includes;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
|
||||
|
||||
class FooVariadic
|
||||
{
|
||||
public function __construct(Foo $foo)
|
||||
{
|
||||
}
|
||||
|
||||
public function bar(...$arguments)
|
||||
{
|
||||
}
|
||||
}
|
@ -156,14 +156,14 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testLoadUserByUsernameFailsIfEntryHasNoUidKeyAttribute()
|
||||
{
|
||||
$result = $this->getMock(CollectionInterface::class);
|
||||
$query = $this->getMock(QueryInterface::class);
|
||||
$result = $this->getMockBuilder(CollectionInterface::class)->getMock();
|
||||
$query = $this->getMockBuilder(QueryInterface::class)->getMock();
|
||||
$query
|
||||
->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue($result))
|
||||
;
|
||||
$ldap = $this->getMock(LdapInterface::class);
|
||||
$ldap = $this->getMockBuilder(LdapInterface::class)->getMock();
|
||||
$result
|
||||
->expects($this->once())
|
||||
->method('offsetGet')
|
||||
@ -321,14 +321,14 @@ class LdapUserProviderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testLoadUserByUsernameIsSuccessfulWithPasswordAttribute()
|
||||
{
|
||||
$result = $this->getMock(CollectionInterface::class);
|
||||
$query = $this->getMock(QueryInterface::class);
|
||||
$result = $this->getMockBuilder(CollectionInterface::class)->getMock();
|
||||
$query = $this->getMockBuilder(QueryInterface::class)->getMock();
|
||||
$query
|
||||
->expects($this->once())
|
||||
->method('execute')
|
||||
->will($this->returnValue($result))
|
||||
;
|
||||
$ldap = $this->getMock(LdapInterface::class);
|
||||
$ldap = $this->getMockBuilder(LdapInterface::class)->getMock();
|
||||
$result
|
||||
->expects($this->once())
|
||||
->method('offsetGet')
|
||||
|
@ -192,7 +192,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="51">
|
||||
<source>No temporary folder was configured in php.ini.</source>
|
||||
<target>Es wurde kein temporärer Ordner in der php.ini konfiguriert.</target>
|
||||
<target>Es wurde kein temporärer Ordner in der php.ini konfiguriert oder der temporäre Ordner existiert nicht.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="52">
|
||||
<source>Cannot write temporary file to disk.</source>
|
||||
|
@ -192,7 +192,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="51">
|
||||
<source>No temporary folder was configured in php.ini.</source>
|
||||
<target>No temporary folder was configured in php.ini.</target>
|
||||
<target>No temporary folder was configured in php.ini, or the configured folder does not exist.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="52">
|
||||
<source>Cannot write temporary file to disk.</source>
|
||||
|
@ -192,7 +192,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="51">
|
||||
<source>No temporary folder was configured in php.ini.</source>
|
||||
<target>Er is geen tijdelijke map geconfigureerd in php.ini.</target>
|
||||
<target>Er is geen tijdelijke map geconfigureerd in php.ini, of de gespecificeerde map bestaat niet.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="52">
|
||||
<source>Cannot write temporary file to disk.</source>
|
||||
|
@ -192,7 +192,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="51">
|
||||
<source>No temporary folder was configured in php.ini.</source>
|
||||
<target>Nie skonfigurowano folderu tymczasowego w php.ini.</target>
|
||||
<target>Nie skonfigurowano folderu tymczasowego w php.ini, lub skonfigurowany folder nie istnieje.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="52">
|
||||
<source>Cannot write temporary file to disk.</source>
|
||||
|
Reference in New Issue
Block a user