Skip to content

Commit

Permalink
feature #22081 [FrameworkBundle][Validator] Move Validator passes to …
Browse files Browse the repository at this point in the history
…the component (chalasr)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[FrameworkBundle][Validator] Move Validator passes to the component

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

Commits
-------

0b741da Move AddValidatorInitializersrPass & AddConstraintValidatorsPass to the Validator
  • Loading branch information
fabpot committed Mar 22, 2017
2 parents a25fd7d + 0b741da commit c73009a
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 56 deletions.
8 changes: 8 additions & 0 deletions UPGRADE-3.3.md
Expand Up @@ -186,6 +186,14 @@ FrameworkBundle
* The `Symfony\Bundle\FrameworkBundle\Translation\Translator` constructor now takes the
default locale as 3rd argument. Not passing it will trigger an error in 4.0.

* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass`
class has been deprecated and will be removed in 4.0.
Use the `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` class instead.

* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass`
class has been deprecated and will be removed in 4.0.
Use the `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` class instead.

HttpFoundation
--------------

Expand Down
9 changes: 7 additions & 2 deletions UPGRADE-4.0.md
Expand Up @@ -279,8 +279,13 @@ FrameworkBundle
* The `Symfony\Bundle\FrameworkBundle\Translation\Translator` constructor now takes the
default locale as mandatory 3rd argument.

HttpFoundation
---------------
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass` class has been
removed. Use the `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass`
class instead.

* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass` class has been
removed. Use the `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass`
class instead.

HttpFoundation
--------------
Expand Down
4 changes: 4 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Expand Up @@ -40,6 +40,10 @@ CHANGELOG
making `Translator` works with any PSR-11 container
* Added `framework.serializer.mapping` config option allowing to define custom
serialization mapping files and directories
* Deprecated `AddValidatorInitializersPass`, use
`Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` instead
* Deprecated `AddConstraintValidatorsPass`, use
`Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead

3.2.0
-----
Expand Down
Expand Up @@ -11,36 +11,13 @@

namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass as BaseAddConstraintValidatorsPass;

class AddConstraintValidatorsPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('validator.validator_factory')) {
return;
}

$validators = array();
foreach ($container->findTaggedServiceIds('validator.constraint_validator') as $id => $attributes) {
$definition = $container->getDefinition($id);

if ($definition->isAbstract()) {
continue;
}

if (isset($attributes[0]['alias'])) {
$validators[$attributes[0]['alias']] = new ServiceClosureArgument(new Reference($id));
}
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', AddConstraintValidatorsPass::class, BaseAddConstraintValidatorsPass::class), E_USER_DEPRECATED);

$validators[$definition->getClass()] = new ServiceClosureArgument(new Reference($id));
}

$container->getDefinition('validator.validator_factory')->replaceArgument(0, (new Definition(ServiceLocator::class, array($validators)))->addTag('container.service_locator'));
}
/**
* @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseAddConstraintValidatorsPass} instead
*/
class AddConstraintValidatorsPass extends BaseAddConstraintValidatorsPass
{
}
Expand Up @@ -11,25 +11,13 @@

namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass as BaseAddValidatorsInitializerPass;

class AddValidatorInitializersPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('validator.builder')) {
return;
}

$validatorBuilder = $container->getDefinition('validator.builder');

$initializers = array();
foreach ($container->findTaggedServiceIds('validator.initializer') as $id => $attributes) {
$initializers[] = new Reference($id);
}
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', AddValidatorInitializersPass::class, BaseAddValidatorsInitializerPass::class), E_USER_DEPRECATED);

$validatorBuilder->addMethodCall('addObjectInitializers', array($initializers));
}
/**
* @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseAddValidatorInitializersPass} instead
*/
class AddValidatorInitializersPass extends BaseAddValidatorsInitializerPass
{
}
8 changes: 4 additions & 4 deletions src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
Expand Up @@ -12,9 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle;

use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddValidatorInitializersPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheCollectorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass;
Expand Down Expand Up @@ -47,6 +45,8 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\Config\Resource\ClassExistenceResource;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;

/**
* Bundle.
Expand Down Expand Up @@ -84,9 +84,9 @@ public function build(ContainerBuilder $container)
// but as late as possible to get resolved parameters
$container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new TemplatingPass());
$container->addCompilerPass(new AddConstraintValidatorsPass(), PassConfig::TYPE_BEFORE_REMOVING);
$this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class, PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new AddValidatorInitializersPass());
$this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class);
$this->addCompilerPassIfExists($container, AddConsoleCommandPass::class);
$container->addCompilerPass(new TranslatorPass());
$container->addCompilerPass(new LoggingTranslatorPass());
Expand Down
Expand Up @@ -19,6 +19,9 @@
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;

/**
* @group legacy
*/
class AddConstraintValidatorsPassTest extends TestCase
{
public function testThatConstraintValidatorServicesAreProcessed()
Expand Down
Expand Up @@ -16,7 +16,6 @@
use Symfony\Bundle\FullStack;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
Expand All @@ -41,6 +40,7 @@
use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;

abstract class FrameworkExtensionTest extends TestCase
{
Expand Down
6 changes: 6 additions & 0 deletions src/Symfony/Component/Validator/CHANGELOG.md
@@ -1,6 +1,12 @@
CHANGELOG
=========

3.3.0
-----

* added `AddValidatorInitializersPass`
* added `AddConstraintValidatorsPass`

3.2.0
-----

Expand Down
@@ -0,0 +1,62 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Validator\DependencyInjection;

use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;

/**
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
* @author Robin Chalas <robin.chalas@gmail.com>
*/
class AddConstraintValidatorsPass implements CompilerPassInterface
{
private $validatorFactoryServiceId;
private $constraintValidatorTag;

public function __construct($validatorFactoryServiceId = 'validator.validator_factory', $constraintValidatorTag = 'validator.constraint_validator')
{
$this->validatorFactoryServiceId = $validatorFactoryServiceId;
$this->constraintValidatorTag = $constraintValidatorTag;
}

public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition($this->validatorFactoryServiceId)) {
return;
}

$validators = array();
foreach ($container->findTaggedServiceIds($this->constraintValidatorTag) as $id => $attributes) {
$definition = $container->getDefinition($id);

if ($definition->isAbstract()) {
continue;
}

if (isset($attributes[0]['alias'])) {
$validators[$attributes[0]['alias']] = new ServiceClosureArgument(new Reference($id));
}

$validators[$definition->getClass()] = new ServiceClosureArgument(new Reference($id));
}

$container
->getDefinition('validator.validator_factory')
->replaceArgument(0, (new Definition(ServiceLocator::class, array($validators)))->addTag('container.service_locator'))
;
}
}
@@ -0,0 +1,50 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Validator\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

/**
* @author Fabien Potencier <fabien@symfony.com>
* @author Robin Chalas <robin.chalas@gmail.com>
*/
class AddValidatorInitializersPass implements CompilerPassInterface
{
private $builderService;
private $initializerTag;

public function __construct($builderService = 'validator.builder', $initializerTag = 'validator.initializer')
{
$this->builderService = $builderService;
$this->initializerTag = $initializerTag;
}

public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition($this->builderService)) {
return;
}

$initializers = array();
foreach ($container->findTaggedServiceIds($this->initializerTag) as $id => $attributes) {
if ($container->getDefinition($id)->isAbstract()) {
continue;
}

$initializers[] = new Reference($id);
}

$container->getDefinition($this->builderService)->addMethodCall('addObjectInitializers', array($initializers));
}
}
@@ -0,0 +1,64 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Validator\Tests\DependencyInjection;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;

class AddConstraintValidatorsPassTest extends TestCase
{
public function testThatConstraintValidatorServicesAreProcessed()
{
$container = new ContainerBuilder();
$validatorFactory = $container->register('validator.validator_factory')
->addArgument(array());

$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 Definition(ServiceLocator::class, array(array(
Validator1::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')),
'my_constraint_validator_alias1' => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')),
Validator2::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service2')),
))))->addTag('container.service_locator'), $validatorFactory->getArgument(0));
}

public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition()
{
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock();
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock();

$container->expects($this->never())->method('findTaggedServiceIds');
$container->expects($this->never())->method('getDefinition');
$container->expects($this->atLeastOnce())
->method('hasDefinition')
->with('validator.validator_factory')
->will($this->returnValue(false));
$definition->expects($this->never())->method('replaceArgument');

$addConstraintValidatorsPass = new AddConstraintValidatorsPass();
$addConstraintValidatorsPass->process($container);
}
}

0 comments on commit c73009a

Please sign in to comment.