[DependencyInjection] Use a service locator in AddConstraintValidatorsPass
This commit is contained in:
parent
7f27787dd0
commit
597b6bcab6
|
@ -143,6 +143,11 @@ FrameworkBundle
|
||||||
deprecated and will be removed in 4.0. Use the `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass`
|
deprecated and will be removed in 4.0. Use the `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass`
|
||||||
class instead.
|
class instead.
|
||||||
|
|
||||||
|
* The `ConstraintValidatorFactory::$validators` and `$container` properties
|
||||||
|
have been deprecated and will be removed in 4.0.
|
||||||
|
|
||||||
|
* Extending `ConstraintValidatorFactory` is deprecated and won't be supported in 4.0.
|
||||||
|
|
||||||
HttpKernel
|
HttpKernel
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,11 @@ FrameworkBundle
|
||||||
removed. Use the `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass`
|
removed. Use the `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass`
|
||||||
class instead.
|
class instead.
|
||||||
|
|
||||||
|
* The `ConstraintValidatorFactory::$validators` and `$container` properties
|
||||||
|
have been removed.
|
||||||
|
|
||||||
|
* Extending `ConstraintValidatorFactory` is not supported anymore.
|
||||||
|
|
||||||
HttpFoundation
|
HttpFoundation
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -243,7 +248,7 @@ HttpKernel
|
||||||
|
|
||||||
* The `Psr6CacheClearer::addPool()` method has been removed. Pass an array of pools indexed
|
* The `Psr6CacheClearer::addPool()` method has been removed. Pass an array of pools indexed
|
||||||
by name to the constructor instead.
|
by name to the constructor instead.
|
||||||
|
|
||||||
* The `LazyLoadingFragmentHandler::addRendererService()` method has been removed.
|
* The `LazyLoadingFragmentHandler::addRendererService()` method has been removed.
|
||||||
|
|
||||||
* The `X-Status-Code` header method of setting a custom status code in the
|
* The `X-Status-Code` header method of setting a custom status code in the
|
||||||
|
@ -310,7 +315,7 @@ Translation
|
||||||
TwigBundle
|
TwigBundle
|
||||||
----------
|
----------
|
||||||
|
|
||||||
* The `ContainerAwareRuntimeLoader` class has been removed. Use the
|
* The `ContainerAwareRuntimeLoader` class has been removed. Use the
|
||||||
Twig `Twig_ContainerRuntimeLoader` class instead.
|
Twig `Twig_ContainerRuntimeLoader` class instead.
|
||||||
|
|
||||||
TwigBridge
|
TwigBridge
|
||||||
|
|
|
@ -17,9 +17,10 @@ CHANGELOG
|
||||||
* Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead
|
* Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead
|
||||||
* Deprecated `SessionListener`
|
* Deprecated `SessionListener`
|
||||||
* Deprecated `TestSessionListener`
|
* Deprecated `TestSessionListener`
|
||||||
* Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`.
|
* Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`.
|
||||||
Use `Symfony\Component\Console\DependencyInjection\ConfigCachePass` instead.
|
Use `Symfony\Component\Console\DependencyInjection\ConfigCachePass` instead.
|
||||||
* Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead
|
* Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead
|
||||||
|
* Deprecated extending `ConstraintValidatorFactory`
|
||||||
|
|
||||||
3.2.0
|
3.2.0
|
||||||
-----
|
-----
|
||||||
|
@ -31,7 +32,7 @@ CHANGELOG
|
||||||
* Removed `symfony/asset` from the list of required dependencies in `composer.json`
|
* Removed `symfony/asset` from the list of required dependencies in `composer.json`
|
||||||
* The `Resources/public/images/*` files have been removed.
|
* The `Resources/public/images/*` files have been removed.
|
||||||
* The `Resources/public/css/*.css` files have been removed (they are now inlined in TwigBundle).
|
* The `Resources/public/css/*.css` files have been removed (they are now inlined in TwigBundle).
|
||||||
* Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension`
|
* Added possibility to prioritize form type extensions with `'priority'` attribute on tags `form.type_extension`
|
||||||
|
|
||||||
3.1.0
|
3.1.0
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
|
|
||||||
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
|
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
class AddConstraintValidatorsPass implements CompilerPassInterface
|
class AddConstraintValidatorsPass implements CompilerPassInterface
|
||||||
{
|
{
|
||||||
|
@ -25,23 +26,19 @@ class AddConstraintValidatorsPass implements CompilerPassInterface
|
||||||
|
|
||||||
$validators = array();
|
$validators = array();
|
||||||
foreach ($container->findTaggedServiceIds('validator.constraint_validator') as $id => $attributes) {
|
foreach ($container->findTaggedServiceIds('validator.constraint_validator') as $id => $attributes) {
|
||||||
if (isset($attributes[0]['alias'])) {
|
|
||||||
$validators[$attributes[0]['alias']] = $id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$definition = $container->getDefinition($id);
|
$definition = $container->getDefinition($id);
|
||||||
|
|
||||||
if (!$definition->isPublic()) {
|
|
||||||
throw new InvalidArgumentException(sprintf('The service "%s" must be public as it can be lazy-loaded.', $id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($definition->isAbstract()) {
|
if ($definition->isAbstract()) {
|
||||||
throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as it can be lazy-loaded.', $id));
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$validators[$definition->getClass()] = $id;
|
if (isset($attributes[0]['alias'])) {
|
||||||
|
$validators[$attributes[0]['alias']] = new Reference($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$validators[$definition->getClass()] = new Reference($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$container->getDefinition('validator.validator_factory')->replaceArgument(1, $validators);
|
$container->getDefinition('validator.validator_factory')->replaceArgument(0, new ServiceLocatorArgument($validators));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,7 @@
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="validator.validator_factory" class="Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory" public="false">
|
<service id="validator.validator_factory" class="Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory" public="false">
|
||||||
<argument type="service" id="service_container" />
|
<argument type="service-locator" /> <!-- Constraint validators locator -->
|
||||||
<argument type="collection" />
|
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="validator.expression" class="Symfony\Component\Validator\Constraints\ExpressionValidator">
|
<service id="validator.expression" class="Symfony\Component\Validator\Constraints\ExpressionValidator">
|
||||||
|
|
|
@ -13,56 +13,34 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
|
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
class AddConstraintValidatorsPassTest extends TestCase
|
class AddConstraintValidatorsPassTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testThatConstraintValidatorServicesAreProcessed()
|
public function testThatConstraintValidatorServicesAreProcessed()
|
||||||
{
|
{
|
||||||
$services = array(
|
$container = new ContainerBuilder();
|
||||||
'my_constraint_validator_service1' => array(0 => array('alias' => 'my_constraint_validator_alias1')),
|
$validatorFactory = $container->register('validator.validator_factory')
|
||||||
'my_constraint_validator_service2' => array(),
|
->setArguments(array(new ServiceLocatorArgument()));
|
||||||
);
|
|
||||||
|
|
||||||
$validatorFactoryDefinition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
|
$container->register('my_constraint_validator_service1', Validator1::class)
|
||||||
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'getDefinition', 'hasDefinition'))->getMock();
|
->addTag('validator.constraint_validator', array('alias' => 'my_constraint_validator_alias1'));
|
||||||
|
$container->register('my_constraint_validator_service2', Validator2::class)
|
||||||
$validatorDefinition1 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock();
|
->addTag('validator.constraint_validator');
|
||||||
$validatorDefinition2 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock();
|
$container->register('my_abstract_constraint_validator')
|
||||||
|
->setAbstract(true)
|
||||||
$validatorDefinition1->expects($this->atLeastOnce())
|
->addTag('validator.constraint_validator');
|
||||||
->method('getClass')
|
|
||||||
->willReturn('My\Fully\Qualified\Class\Named\Validator1');
|
|
||||||
$validatorDefinition2->expects($this->atLeastOnce())
|
|
||||||
->method('getClass')
|
|
||||||
->willReturn('My\Fully\Qualified\Class\Named\Validator2');
|
|
||||||
|
|
||||||
$container->expects($this->any())
|
|
||||||
->method('getDefinition')
|
|
||||||
->with($this->anything())
|
|
||||||
->will($this->returnValueMap(array(
|
|
||||||
array('my_constraint_validator_service1', $validatorDefinition1),
|
|
||||||
array('my_constraint_validator_service2', $validatorDefinition2),
|
|
||||||
array('validator.validator_factory', $validatorFactoryDefinition),
|
|
||||||
)));
|
|
||||||
|
|
||||||
$container->expects($this->atLeastOnce())
|
|
||||||
->method('findTaggedServiceIds')
|
|
||||||
->will($this->returnValue($services));
|
|
||||||
$container->expects($this->atLeastOnce())
|
|
||||||
->method('hasDefinition')
|
|
||||||
->with('validator.validator_factory')
|
|
||||||
->will($this->returnValue(true));
|
|
||||||
|
|
||||||
$validatorFactoryDefinition->expects($this->once())
|
|
||||||
->method('replaceArgument')
|
|
||||||
->with(1, array(
|
|
||||||
'My\Fully\Qualified\Class\Named\Validator1' => 'my_constraint_validator_service1',
|
|
||||||
'my_constraint_validator_alias1' => 'my_constraint_validator_service1',
|
|
||||||
'My\Fully\Qualified\Class\Named\Validator2' => 'my_constraint_validator_service2',
|
|
||||||
));
|
|
||||||
|
|
||||||
$addConstraintValidatorsPass = new AddConstraintValidatorsPass();
|
$addConstraintValidatorsPass = new AddConstraintValidatorsPass();
|
||||||
$addConstraintValidatorsPass->process($container);
|
$addConstraintValidatorsPass->process($container);
|
||||||
|
|
||||||
|
$this->assertEquals(new ServiceLocatorArgument(array(
|
||||||
|
Validator1::class => new Reference('my_constraint_validator_service1'),
|
||||||
|
'my_constraint_validator_alias1' => new Reference('my_constraint_validator_service1'),
|
||||||
|
Validator2::class => new Reference('my_constraint_validator_service2'),
|
||||||
|
)), $validatorFactory->getArgument(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition()
|
public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition()
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace Symfony\Bundle\FrameworkBundle\Validator;
|
namespace Symfony\Bundle\FrameworkBundle\Validator;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Symfony\Component\Validator\Constraint;
|
use Symfony\Component\Validator\Constraint;
|
||||||
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
|
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
|
||||||
use Symfony\Component\Validator\ConstraintValidatorInterface;
|
use Symfony\Component\Validator\ConstraintValidatorInterface;
|
||||||
|
@ -37,6 +37,8 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* @author Kris Wallsmith <kris@symfony.com>
|
* @author Kris Wallsmith <kris@symfony.com>
|
||||||
|
*
|
||||||
|
* @final since version 3.3
|
||||||
*/
|
*/
|
||||||
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
|
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
|
||||||
{
|
{
|
||||||
|
@ -70,11 +72,15 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
|
||||||
$name = $constraint->validatedBy();
|
$name = $constraint->validatedBy();
|
||||||
|
|
||||||
if (!isset($this->validators[$name])) {
|
if (!isset($this->validators[$name])) {
|
||||||
if (!class_exists($name)) {
|
if ($this->container->has($name)) {
|
||||||
throw new ValidatorException(sprintf('Constraint validator "%s" does not exist or it is not enabled. Check the "validatedBy" method in your constraint class "%s".', $name, get_class($constraint)));
|
$this->validators[$name] = $this->container->get($name);
|
||||||
}
|
} else {
|
||||||
|
if (!class_exists($name)) {
|
||||||
|
throw new ValidatorException(sprintf('Constraint validator "%s" does not exist or it is not enabled. Check the "validatedBy" method in your constraint class "%s".', $name, get_class($constraint)));
|
||||||
|
}
|
||||||
|
|
||||||
$this->validators[$name] = new $name();
|
$this->validators[$name] = new $name();
|
||||||
|
}
|
||||||
} elseif (is_string($this->validators[$name])) {
|
} elseif (is_string($this->validators[$name])) {
|
||||||
$this->validators[$name] = $this->container->get($this->validators[$name]);
|
$this->validators[$name] = $this->container->get($this->validators[$name]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
"symfony/serializer": "~3.3",
|
"symfony/serializer": "~3.3",
|
||||||
"symfony/translation": "~2.8|~3.0",
|
"symfony/translation": "~2.8|~3.0",
|
||||||
"symfony/templating": "~2.8|~3.0",
|
"symfony/templating": "~2.8|~3.0",
|
||||||
"symfony/validator": "~3.2",
|
"symfony/validator": "~3.3",
|
||||||
"symfony/yaml": "~3.2",
|
"symfony/yaml": "~3.2",
|
||||||
"symfony/property-info": "~3.3",
|
"symfony/property-info": "~3.3",
|
||||||
"doctrine/annotations": "~1.0",
|
"doctrine/annotations": "~1.0",
|
||||||
|
@ -65,7 +65,8 @@
|
||||||
"symfony/console": "<3.3",
|
"symfony/console": "<3.3",
|
||||||
"symfony/serializer": "<3.3",
|
"symfony/serializer": "<3.3",
|
||||||
"symfony/form": "<3.3",
|
"symfony/form": "<3.3",
|
||||||
"symfony/property-info": "<3.3"
|
"symfony/property-info": "<3.3",
|
||||||
|
"symfony/validator": "<3.3"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-apcu": "For best performance of the system caches",
|
"ext-apcu": "For best performance of the system caches",
|
||||||
|
|
Reference in New Issue