Skip to content

Commit

Permalink
Add GroupProviderInterface
Browse files Browse the repository at this point in the history
  • Loading branch information
yceruto committed Aug 17, 2023
1 parent 5f0a94b commit d21df03
Show file tree
Hide file tree
Showing 31 changed files with 191 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class UnusedTagsPass implements CompilerPassInterface
'twig.runtime',
'validator.auto_mapper',
'validator.constraint_validator',
'validator.group_sequence_provider',
'validator.group_provider',
'validator.initializer',
'workflow',
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
use Symfony\Component\Uid\UuidV4;
use Symfony\Component\Validator\Constraints\WhenValidator;
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\GroupProviderInterface;
use Symfony\Component\Validator\GroupSequenceProviderInterface;
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
use Symfony\Component\Validator\ObjectInitializerInterface;
Expand Down Expand Up @@ -670,8 +671,8 @@ public function load(array $configs, ContainerBuilder $container)
->addTag('serializer.normalizer');
$container->registerForAutoconfiguration(ConstraintValidatorInterface::class)
->addTag('validator.constraint_validator');
$container->registerForAutoconfiguration(GroupSequenceProviderInterface::class)
->addTag('validator.group_sequence_provider');
$container->registerForAutoconfiguration(GroupProviderInterface::class)
->addTag('validator.group_provider');
$container->registerForAutoconfiguration(ObjectInitializerInterface::class)
->addTag('validator.initializer');
$container->registerForAutoconfiguration(MessageHandlerInterface::class)
Expand Down
4 changes: 2 additions & 2 deletions src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
use Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass;
use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
use Symfony\Component\Validator\DependencyInjection\AddGroupSequenceProvidersPass;
use Symfony\Component\Validator\DependencyInjection\AddGroupProvidersPass;
use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;
use Symfony\Component\VarExporter\Internal\Hydrator;
use Symfony\Component\VarExporter\Internal\Registry;
Expand Down Expand Up @@ -149,7 +149,7 @@ public function build(ContainerBuilder $container)
// but as late as possible to get resolved parameters
$container->addCompilerPass($registerListenersPass, PassConfig::TYPE_BEFORE_REMOVING);
$this->addCompilerPassIfExists($container, AddConstraintValidatorsPass::class);
$this->addCompilerPassIfExists($container, AddGroupSequenceProvidersPass::class);
$this->addCompilerPassIfExists($container, AddGroupProvidersPass::class);
$container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_AFTER_REMOVING, -255);
$this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class);
$this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use Symfony\Component\Validator\Constraints\NotCompromisedPasswordValidator;
use Symfony\Component\Validator\Constraints\WhenValidator;
use Symfony\Component\Validator\ContainerConstraintValidatorFactory;
use Symfony\Component\Validator\ContainerGroupSequenceProviderFactory;
use Symfony\Component\Validator\ContainerGroupProviderFactory;
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Validator\ValidatorInterface;
Expand All @@ -42,8 +42,8 @@
->call('setConstraintValidatorFactory', [
service('validator.validator_factory'),
])
->call('setGroupSequenceProviderFactory', [
service('validator.group_sequence_provider_factory'),
->call('setGroupProviderFactory', [
service('validator.group_provider_factory'),
])
->call('setTranslator', [
service('translator')->ignoreOnInvalid(),
Expand Down Expand Up @@ -72,9 +72,9 @@
abstract_arg('Constraint validators locator'),
])

->set('validator.group_sequence_provider_factory', ContainerGroupSequenceProviderFactory::class)
->set('validator.group_provider_factory', ContainerGroupProviderFactory::class)
->args([
abstract_arg('Group sequence provider locator'),
abstract_arg('Group provider locator'),
])

->load('Symfony\Component\Validator\Constraints\\', $validatorsDir.'/*Validator.php')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
use Symfony\Component\Translation\LocaleSwitcher;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
use Symfony\Component\Validator\DependencyInjection\AddGroupSequenceProvidersPass;
use Symfony\Component\Validator\DependencyInjection\AddGroupProvidersPass;
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\Validator\ValidatorBuilder;
Expand Down Expand Up @@ -1234,8 +1234,8 @@ public function testValidation()
$this->assertCount($annotations ? 8 : 7, $calls);
$this->assertSame('setConstraintValidatorFactory', $calls[0][0]);
$this->assertEquals([new Reference('validator.validator_factory')], $calls[0][1]);
$this->assertSame('setGroupSequenceProviderFactory', $calls[1][0]);
$this->assertEquals([new Reference('validator.group_sequence_provider_factory')], $calls[1][1]);
$this->assertSame('setGroupProviderFactory', $calls[1][0]);
$this->assertEquals([new Reference('validator.group_provider_factory')], $calls[1][1]);
$this->assertSame('setTranslator', $calls[2][0]);
$this->assertEquals([new Reference('translator', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE)], $calls[2][1]);
$this->assertSame('setTranslationDomain', $calls[3][0]);
Expand Down Expand Up @@ -2385,7 +2385,7 @@ protected function createContainerFromFile(string $file, array $data = [], bool
$container->getCompilerPassConfig()->setAfterRemovingPasses([]);
}
$container->getCompilerPassConfig()->setBeforeOptimizationPasses([new LoggerPass()]);
$container->getCompilerPassConfig()->setBeforeRemovingPasses([new AddConstraintValidatorsPass(), new AddGroupSequenceProvidersPass(), new TranslatorPass()]);
$container->getCompilerPassConfig()->setBeforeRemovingPasses([new AddConstraintValidatorsPass(), new AddGroupProvidersPass(), new TranslatorPass()]);
$container->getCompilerPassConfig()->setAfterRemovingPasses([new AddAnnotationsCachedReaderPass()]);

if (!$compile) {
Expand Down
2 changes: 1 addition & 1 deletion src/Symfony/Component/Validator/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ CHANGELOG
* Deprecate `ValidatorBuilder::addDefaultDoctrineAnnotationReader()`
* Add `number`, `finite-number` and `finite-float` types to `Type` constraint
* Add the `withSeconds` option to the `Time` constraint that allows to pass time without seconds
* Add support for implementing `GroupSequenceProviderInterface` outside of the underlying class
* Add `GroupProviderInterface` to implement validation group providers outside the underlying class

6.3
---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,34 @@
use Symfony\Component\Validator\Exception\UnexpectedTypeException;

/**
* Factory class leveraging a PSR-11 container to create or retrieve instances of group sequence providers.
* Factory class leveraging a PSR-11 container to create or retrieve instances of validation group providers.
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
class ContainerGroupSequenceProviderFactory implements GroupSequenceProviderFactoryInterface
class ContainerGroupProviderFactory implements GroupProviderFactoryInterface
{
private array $providers = [];

public function __construct(private readonly ContainerInterface $container)
{
}

public function getInstance(string $class): GroupSequenceProviderInterface
public function getInstance(string $class): GroupProviderInterface
{
if (!isset($this->providers[$class])) {
if ($this->container->has($class)) {
$this->providers[$class] = $this->container->get($class);
} else {
if (!class_exists($class)) {
throw new GroupDefinitionException(sprintf('Group sequence provider "%s" does not exist or is not enabled as service. Check the "class" option in your constraint class "%s".', $class, GroupSequenceProvider::class));
throw new GroupDefinitionException(sprintf('Group provider "%s" does not exist or is not enabled as service. Check the "class" option in your constraint class "%s".', $class, GroupSequenceProvider::class));
}

$this->providers[$class] = new $class();
}
}

if (!$this->providers[$class] instanceof GroupSequenceProviderInterface) {
throw new UnexpectedTypeException($this->providers[$class], GroupSequenceProviderInterface::class);
if (!$this->providers[$class] instanceof GroupProviderInterface) {
throw new UnexpectedTypeException($this->providers[$class], GroupProviderInterface::class);
}

return $this->providers[$class];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@
/**
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
class AddGroupSequenceProvidersPass implements CompilerPassInterface
class AddGroupProvidersPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (!$container->hasDefinition('validator.group_sequence_provider_factory')) {
if (!$container->hasDefinition('validator.group_provider_factory')) {
return;
}

$providers = [];
foreach ($container->findTaggedServiceIds('validator.group_sequence_provider', true) as $id => $attributes) {
foreach ($container->findTaggedServiceIds('validator.group_provider', true) as $id => $attributes) {
$definition = $container->getDefinition($id);

if (isset($attributes[0]['alias'])) {
Expand All @@ -39,7 +39,7 @@ public function process(ContainerBuilder $container): void
}

$container
->getDefinition('validator.group_sequence_provider_factory')
->getDefinition('validator.group_provider_factory')
->replaceArgument(0, ServiceLocatorTagPass::register($container, $providers))
;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@
namespace Symfony\Component\Validator;

/**
* Factory class for creating or retrieving instances of group sequence providers.
* Factory class for creating or retrieving instances of validation group providers.
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
class GroupSequenceProviderFactory implements GroupSequenceProviderFactoryInterface
class GroupProviderFactory implements GroupProviderFactoryInterface
{
public function __construct(private array $providers = [])
{
}

public function getInstance(string $class): GroupSequenceProviderInterface
public function getInstance(string $class): GroupProviderInterface
{
return $this->providers[$class] ??= new $class();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
namespace Symfony\Component\Validator;

/**
* Handles the creation of group sequence providers.
* Handles the creation of validation group providers.
*
* @author Yonel Ceruto <yonelceruto@gmail.com>
*/
interface GroupSequenceProviderFactoryInterface
interface GroupProviderFactoryInterface
{
public function getInstance(string $class): GroupSequenceProviderInterface;
public function getInstance(string $class): GroupProviderInterface;
}
28 changes: 28 additions & 0 deletions src/Symfony/Component/Validator/GroupProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?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;

use Symfony\Component\Validator\Constraints\GroupSequence;

/**
* Defines the interface for a validation group provider.
*/
interface GroupProviderInterface
{
/**
* Returns which validation groups should be used for a certain state
* of the object.
*
* @return string[]|string[][]|GroupSequence
*/
public function getGroups(object $object): array|GroupSequence;
}
18 changes: 9 additions & 9 deletions src/Symfony/Component/Validator/Mapping/ClassMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface
/**
* @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use
* {@link getGroupSequenceProviderClass()} instead.
* {@link getGroupProviderClass()} instead.
*/
public ?string $groupSequenceProviderClass = null;
public ?string $groupProviderClass = null;

/**
* The strategy for traversing traversable objects.
Expand Down Expand Up @@ -130,7 +130,7 @@ public function __sleep(): array
'getters',
'groupSequence',
'groupSequenceProvider',
'groupSequenceProviderClass',
'groupProviderClass',
'members',
'name',
'properties',
Expand Down Expand Up @@ -327,7 +327,7 @@ public function addGetterMethodConstraints(string $property, string $method, arr
public function mergeConstraints(self $source)
{
if ($source->isGroupSequenceProvider()) {
$this->setGroupSequenceProviderClass($source->getGroupSequenceProviderClass());
$this->setGroupProviderClass($source->getGroupProviderClass());
$this->setGroupSequenceProvider(true);
}

Expand Down Expand Up @@ -441,7 +441,7 @@ public function setGroupSequenceProvider(bool $active)
throw new GroupDefinitionException('Defining a group sequence provider is not allowed with a static group sequence.');
}

if (null === $this->groupSequenceProviderClass && !$this->getReflectionClass()->implementsInterface(GroupSequenceProviderInterface::class)) {
if (null === $this->groupProviderClass && !$this->getReflectionClass()->implementsInterface(GroupSequenceProviderInterface::class)) {
throw new GroupDefinitionException(sprintf('Class "%s" must implement GroupSequenceProviderInterface.', $this->name));
}

Expand All @@ -453,14 +453,14 @@ public function isGroupSequenceProvider(): bool
return $this->groupSequenceProvider;
}

public function setGroupSequenceProviderClass(?string $class): void
public function setGroupProviderClass(?string $class): void
{
$this->groupSequenceProviderClass = $class;
$this->groupProviderClass = $class;
}

public function getGroupSequenceProviderClass(): ?string
public function getGroupProviderClass(): ?string
{
return $this->groupSequenceProviderClass;
return $this->groupProviderClass;
}

public function getCascadingStrategy(): int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
* @see GroupSequenceProviderInterface
* @see TraversalStrategy
*
* @method string|null getGroupSequenceProviderClass()
* @method string|null getGroupProviderClass()
*/
interface ClassMetadataInterface extends MetadataInterface
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function loadClassMetadata(ClassMetadata $metadata): bool
if ($constraint instanceof GroupSequence) {
$metadata->setGroupSequence($constraint->groups);
} elseif ($constraint instanceof GroupSequenceProvider) {
$metadata->setGroupSequenceProviderClass($constraint->class);
$metadata->setGroupProviderClass($constraint->class);
$metadata->setGroupSequenceProvider(true);
} elseif ($constraint instanceof Constraint) {
$metadata->addConstraint($constraint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ private function loadClassesFromXml(): void
private function loadClassMetadataFromXml(ClassMetadata $metadata, \SimpleXMLElement $classDescription): void
{
if (\count($classDescription->{'group-sequence-provider'}) > 0) {
$metadata->setGroupSequenceProviderClass($classDescription->{'group-sequence-provider'}[0]->value ?: null);
$metadata->setGroupProviderClass($classDescription->{'group-sequence-provider'}[0]->value ?: null);
$metadata->setGroupSequenceProvider(true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $class
{
if (isset($classDescription['group_sequence_provider'])) {
if (\is_string($classDescription['group_sequence_provider'])) {
$metadata->setGroupSequenceProviderClass($classDescription['group_sequence_provider']);
$metadata->setGroupProviderClass($classDescription['group_sequence_provider']);
}
$metadata->setGroupSequenceProvider(
(bool) $classDescription['group_sequence_provider']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@

use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Constraints\GroupSequenceProvider;
use Symfony\Component\Validator\Tests\Dummy\DummyGroupSequenceProvider;
use Symfony\Component\Validator\Tests\Dummy\DummyGroupProvider;

class GroupSequenceProviderTest extends TestCase
{
public function testCreate()
{
$sequence = new GroupSequenceProvider(['class' => DummyGroupSequenceProvider::class]);
$sequence = new GroupSequenceProvider(['class' => DummyGroupProvider::class]);

$this->assertSame(DummyGroupSequenceProvider::class, $sequence->class);
$this->assertSame(DummyGroupProvider::class, $sequence->class);
}

public function testCreateAttributeStyle()
{
$sequence = new GroupSequenceProvider(class: DummyGroupSequenceProvider::class);
$sequence = new GroupSequenceProvider(class: DummyGroupProvider::class);

$this->assertSame(DummyGroupSequenceProvider::class, $sequence->class);
$this->assertSame(DummyGroupProvider::class, $sequence->class);
}
}

0 comments on commit d21df03

Please sign in to comment.