diff --git a/src/Symfony/Component/Validator/Constraints/UniqueValidator.php b/src/Symfony/Component/Validator/Constraints/UniqueValidator.php index de2edce631837..2233a75e837a2 100644 --- a/src/Symfony/Component/Validator/Constraints/UniqueValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UniqueValidator.php @@ -11,8 +11,12 @@ namespace Symfony\Component\Validator\Constraints; +use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\LogicException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -21,6 +25,13 @@ */ class UniqueValidator extends ConstraintValidator { + private ?PropertyAccessorInterface $propertyAccessor; + + public function __construct(PropertyAccessorInterface $propertyAccessor = null) + { + $this->propertyAccessor = $propertyAccessor; + } + public function validate(mixed $value, Constraint $constraint) { if (!$constraint instanceof Unique) { @@ -69,18 +80,37 @@ private function getNormalizer(Unique $unique): callable return $unique->normalizer; } - private function reduceElementKeys(array $fields, array $element): array + private function reduceElementKeys(array $fields, array|object $element): array { $output = []; foreach ($fields as $field) { if (!\is_string($field)) { throw new UnexpectedTypeException($field, 'string'); } - if (isset($element[$field])) { - $output[$field] = $element[$field]; + + // For no BC, because PropertyAccessor require brackets for array keys + // Previous implementation, only check in array + if (\is_array($element) && !str_contains($field, '[')) { + $field = "[{$field}]"; + } + + if (null !== $value = $this->getPropertyAccessor()->getValue($element, $field)) { + $output[$field] = $value; } } return $output; } + + private function getPropertyAccessor(): PropertyAccessor + { + if (null === $this->propertyAccessor) { + if (!class_exists(PropertyAccess::class)) { + throw new LogicException('Unable to use property path as the Symfony PropertyAccess component is not installed.'); + } + $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); + } + + return $this->propertyAccessor; + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php index 2f045ccf64ff7..7c39dd521da02 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php @@ -280,6 +280,27 @@ public function getInvalidCollectionValues(): array ['id' => 1, 'email' => 'bar@email.com'], ['id' => 1, 'email' => 'foo@email.com'], ], ['id']], + 'unique string sub array' => [[ + ['id' => 1, 'translation' => ['lang' => 'eng', 'translation' => 'hi']], + ['id' => 2, 'translation' => ['lang' => 'eng', 'translation' => 'hello']], + ], ['[translation][lang]']], + 'unique string attribute' => [[ + (object) ['lang' => 'eng', 'translation' => 'hi'], + (object) ['lang' => 'eng', 'translation' => 'hello'], + ], ['lang']], + 'unique float attribute' => [[ + (object) ['latitude' => 51.509865, 'longitude' => -0.118092, 'poi' => 'capital'], + (object) ['latitude' => 52.520008, 'longitude' => 13.404954], + (object) ['latitude' => 51.509865, 'longitude' => -0.118092], + ], ['latitude', 'longitude']], + 'unique int attribute' => [[ + (object) ['id' => 1, 'email' => 'bar@email.com'], + (object) ['id' => 1, 'email' => 'foo@email.com'], + ], ['id']], + 'unique string sub object attribute' => [[ + (object) ['id' => 1, 'translation' => (object) ['lang' => 'eng', 'translation' => 'hi']], + (object) ['id' => 2, 'translation' => (object) ['lang' => 'eng', 'translation' => 'hello']], + ], ['translation.lang']], ]; } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy