diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md
index 65e7e0e0d839e..7f7567bcec410 100644
--- a/UPGRADE-3.3.md
+++ b/UPGRADE-3.3.md
@@ -143,6 +143,11 @@ FrameworkBundle
deprecated and will be removed in 4.0. Use the `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass`
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
-----------
diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md
index daac2d04c5787..7528a6dc2820a 100644
--- a/UPGRADE-4.0.md
+++ b/UPGRADE-4.0.md
@@ -202,6 +202,11 @@ FrameworkBundle
removed. Use the `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass`
class instead.
+ * The `ConstraintValidatorFactory::$validators` and `$container` properties
+ have been removed.
+
+ * Extending `ConstraintValidatorFactory` is not supported anymore.
+
HttpFoundation
---------------
@@ -243,7 +248,7 @@ HttpKernel
* The `Psr6CacheClearer::addPool()` method has been removed. Pass an array of pools indexed
by name to the constructor instead.
-
+
* The `LazyLoadingFragmentHandler::addRendererService()` method has been removed.
* The `X-Status-Code` header method of setting a custom status code in the
@@ -310,7 +315,7 @@ Translation
TwigBundle
----------
-* The `ContainerAwareRuntimeLoader` class has been removed. Use the
+* The `ContainerAwareRuntimeLoader` class has been removed. Use the
Twig `Twig_ContainerRuntimeLoader` class instead.
TwigBridge
diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index d91ae4babbc86..9f8061adc46f3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -17,9 +17,10 @@ CHANGELOG
* Deprecated `FormPass`, use `Symfony\Component\Form\DependencyInjection\FormPass` instead
* Deprecated `SessionListener`
* Deprecated `TestSessionListener`
- * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`.
+ * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`.
Use `Symfony\Component\Console\DependencyInjection\ConfigCachePass` instead.
* Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead
+ * Deprecated extending `ConstraintValidatorFactory`
3.2.0
-----
@@ -31,7 +32,7 @@ CHANGELOG
* Removed `symfony/asset` from the list of required dependencies in `composer.json`
* The `Resources/public/images/*` files have been removed.
* 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
-----
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php
index 497ea08a4bf4e..ec9bd17e99cc0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php
@@ -11,9 +11,10 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
class AddConstraintValidatorsPass implements CompilerPassInterface
{
@@ -25,23 +26,19 @@ public function process(ContainerBuilder $container)
$validators = array();
foreach ($container->findTaggedServiceIds('validator.constraint_validator') as $id => $attributes) {
- if (isset($attributes[0]['alias'])) {
- $validators[$attributes[0]['alias']] = $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()) {
+ continue;
}
- if ($definition->isAbstract()) {
- throw new InvalidArgumentException(sprintf('The service "%s" must not be abstract as it can be lazy-loaded.', $id));
+ if (isset($attributes[0]['alias'])) {
+ $validators[$attributes[0]['alias']] = new Reference($id);
}
- $validators[$definition->getClass()] = $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));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
index 6da59e54e212e..9abf2fbd3dda2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
@@ -57,8 +57,7 @@
-
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php
index e58068900fc8f..53fb8a29e4432 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php
@@ -13,56 +13,34 @@
use PHPUnit\Framework\TestCase;
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
{
public function testThatConstraintValidatorServicesAreProcessed()
{
- $services = array(
- 'my_constraint_validator_service1' => array(0 => array('alias' => 'my_constraint_validator_alias1')),
- 'my_constraint_validator_service2' => array(),
- );
-
- $validatorFactoryDefinition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
- $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds', 'getDefinition', 'hasDefinition'))->getMock();
-
- $validatorDefinition1 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock();
- $validatorDefinition2 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->setMethods(array('getClass'))->getMock();
-
- $validatorDefinition1->expects($this->atLeastOnce())
- ->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',
- ));
+ $container = new ContainerBuilder();
+ $validatorFactory = $container->register('validator.validator_factory')
+ ->setArguments(array(new ServiceLocatorArgument()));
+
+ $container->register('my_constraint_validator_service1', Validator1::class)
+ ->addTag('validator.constraint_validator', array('alias' => 'my_constraint_validator_alias1'));
+ $container->register('my_constraint_validator_service2', Validator2::class)
+ ->addTag('validator.constraint_validator');
+ $container->register('my_abstract_constraint_validator')
+ ->setAbstract(true)
+ ->addTag('validator.constraint_validator');
$addConstraintValidatorsPass = new AddConstraintValidatorsPass();
$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()
diff --git a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php
index 4e36678212baa..aba02e0944e22 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php
@@ -11,7 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\Validator;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Psr\Container\ContainerInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
use Symfony\Component\Validator\ConstraintValidatorInterface;
@@ -37,6 +37,8 @@
* }
*
* @author Kris Wallsmith
+ *
+ * @final since version 3.3
*/
class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
{
@@ -70,11 +72,15 @@ public function getInstance(Constraint $constraint)
$name = $constraint->validatedBy();
if (!isset($this->validators[$name])) {
- 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)));
- }
+ if ($this->container->has($name)) {
+ $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])) {
$this->validators[$name] = $this->container->get($this->validators[$name]);
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index d82fd511b3d65..feaa98826f947 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -49,7 +49,7 @@
"symfony/serializer": "~3.3",
"symfony/translation": "~2.8|~3.0",
"symfony/templating": "~2.8|~3.0",
- "symfony/validator": "~3.2",
+ "symfony/validator": "~3.3",
"symfony/yaml": "~3.2",
"symfony/property-info": "~3.3",
"doctrine/annotations": "~1.0",
@@ -65,7 +65,8 @@
"symfony/console": "<3.3",
"symfony/serializer": "<3.3",
"symfony/form": "<3.3",
- "symfony/property-info": "<3.3"
+ "symfony/property-info": "<3.3",
+ "symfony/validator": "<3.3"
},
"suggest": {
"ext-apcu": "For best performance of the system caches",