From d1cb2d6354bfe92fa8b4bd252c7400ac0cef04f4 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sat, 26 Sep 2020 19:44:58 +0200 Subject: [PATCH] [Validator] Constraints as php 8 Attributes. --- .github/patch-types.php | 1 + .../Tests/Fixtures/Attribute/Foo.php | 3 +- .../Component/Routing/Annotation/Route.php | 4 +- .../Security/Http/Attribute/CurrentUser.php | 3 +- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Component/Validator/Constraint.php | 18 +- .../Component/Validator/Constraints/Blank.php | 8 + .../Validator/Constraints/Callback.php | 17 +- .../Validator/Constraints/Choice.php | 35 ++++ .../Validator/Constraints/GroupSequence.php | 1 + .../Constraints/GroupSequenceProvider.php | 1 + .../Validator/Constraints/IsFalse.php | 8 + .../Validator/Constraints/IsNull.php | 8 + .../Validator/Constraints/IsTrue.php | 8 + .../Validator/Constraints/NotBlank.php | 9 +- .../Validator/Constraints/NotNull.php | 8 + .../Component/Validator/Constraints/Range.php | 80 +++++--- .../Component/Validator/Constraints/Valid.php | 1 + .../Mapping/Loader/AnnotationLoader.php | 40 +++- .../Constraints/CallbackValidatorTest.php | 23 ++- .../Tests/Constraints/ChoiceValidatorTest.php | 170 +++++++++++----- .../Constraints/ExpressionValidatorTest.php | 2 +- .../Constraints/IsFalseValidatorTest.php | 20 +- .../Tests/Constraints/IsNullValidatorTest.php | 16 ++ .../Tests/Constraints/IsTrueValidatorTest.php | 20 +- .../Tests/Constraints/NotBlankTest.php | 30 +++ .../Constraints/NotNullValidatorTest.php | 20 +- .../Validator/Tests/Constraints/RangeTest.php | 23 ++- .../Tests/Constraints/RangeValidatorTest.php | 184 ++++++++++++++++++ .../Fixtures/{ => Annotation}/Entity.php | 3 +- .../{ => Annotation}/EntityParent.php | 3 +- .../GroupSequenceProviderEntity.php | 2 +- .../Tests/Fixtures/Attribute/Entity.php | 145 ++++++++++++++ .../Tests/Fixtures/Attribute/EntityParent.php | 36 ++++ .../Attribute/GroupSequenceProviderEntity.php | 34 ++++ .../Validator/Tests/Fixtures/ConstraintA.php | 1 + .../GroupSequenceProviderChildEntity.php | 2 + .../Tests/Mapping/ClassMetadataTest.php | 9 +- .../LazyLoadingMetadataFactoryTest.php | 6 +- .../Tests/Mapping/GetterMetadataTest.php | 6 +- .../Mapping/Loader/AnnotationLoaderTest.php | 50 +++-- .../Tests/Mapping/Loader/FilesLoaderTest.php | 3 +- .../Mapping/Loader/PropertyInfoLoaderTest.php | 2 +- .../Mapping/Loader/XmlFileLoaderTest.php | 20 +- .../Mapping/Loader/YamlFileLoaderTest.php | 22 ++- .../Tests/Mapping/Loader/bad-format.yml | 2 +- .../Loader/constraint-mapping-non-strings.xml | 2 +- .../Mapping/Loader/constraint-mapping.xml | 4 +- .../Mapping/Loader/constraint-mapping.yml | 4 +- .../Mapping/Loader/mapping-with-constants.yml | 2 +- .../Tests/Mapping/Loader/withdoctype.xml | 2 +- .../Tests/Mapping/MemberMetadataTest.php | 3 +- .../Tests/Mapping/PropertyMetadataTest.php | 7 +- .../Tests/Validator/AbstractTest.php | 2 +- .../Tests/Validator/AbstractValidatorTest.php | 6 +- .../Validator/RecursiveValidatorTest.php | 4 +- .../VarDumper/Tests/Fixtures/MyAttribute.php | 4 +- .../Tests/Fixtures/RepeatableAttribute.php | 4 +- .../Contracts/Service/Attribute/Required.php | 4 +- 59 files changed, 957 insertions(+), 199 deletions(-) rename src/Symfony/Component/Validator/Tests/Fixtures/{ => Annotation}/Entity.php (95%) rename src/Symfony/Component/Validator/Tests/Fixtures/{ => Annotation}/EntityParent.php (83%) rename src/Symfony/Component/Validator/Tests/Fixtures/{ => Annotation}/GroupSequenceProviderEntity.php (91%) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/Attribute/Entity.php create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/Attribute/EntityParent.php create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/Attribute/GroupSequenceProviderEntity.php diff --git a/.github/patch-types.php b/.github/patch-types.php index a2999b77b5..3c91c7f580 100644 --- a/.github/patch-types.php +++ b/.github/patch-types.php @@ -36,6 +36,7 @@ foreach ($loader->getClassMap() as $class => $file) { case false !== strpos($file, '/src/Symfony/Component/Routing/Tests/Fixtures/AttributeFixtures'): case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/LotsOfAttributes.php'): + case false !== strpos($file, '/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/MyAttribute.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/Php74.php') && \PHP_VERSION_ID < 70400: diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Attribute/Foo.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Attribute/Foo.php index d932d0584a..96a03adaad 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Attribute/Foo.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Attribute/Foo.php @@ -11,10 +11,9 @@ namespace Symfony\Component\HttpKernel\Tests\Fixtures\Attribute; -use Attribute; use Symfony\Component\HttpKernel\Attribute\ArgumentInterface; -#[Attribute(Attribute::TARGET_PARAMETER)] +#[\Attribute(\Attribute::TARGET_PARAMETER)] class Foo implements ArgumentInterface { private $foo; diff --git a/src/Symfony/Component/Routing/Annotation/Route.php b/src/Symfony/Component/Routing/Annotation/Route.php index d575cb7fdf..f51b74c387 100644 --- a/src/Symfony/Component/Routing/Annotation/Route.php +++ b/src/Symfony/Component/Routing/Annotation/Route.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Routing\Annotation; -use Attribute; - /** * Annotation class for @Route(). * @@ -22,7 +20,7 @@ use Attribute; * @author Fabien Potencier * @author Alexander M. Turek */ -#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] +#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)] class Route { private $path; diff --git a/src/Symfony/Component/Security/Http/Attribute/CurrentUser.php b/src/Symfony/Component/Security/Http/Attribute/CurrentUser.php index 1f503dd6c1..e9202ed2b3 100644 --- a/src/Symfony/Component/Security/Http/Attribute/CurrentUser.php +++ b/src/Symfony/Component/Security/Http/Attribute/CurrentUser.php @@ -11,13 +11,12 @@ namespace Symfony\Component\Security\Http\Attribute; -use Attribute; use Symfony\Component\HttpKernel\Attribute\ArgumentInterface; /** * Indicates that a controller argument should receive the current logged user. */ -#[Attribute(Attribute::TARGET_PARAMETER)] +#[\Attribute(\Attribute::TARGET_PARAMETER)] class CurrentUser implements ArgumentInterface { } diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 043f310f35..44ce55ab15 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -32,6 +32,7 @@ CHANGELOG * added the `Isin` constraint and validator * added the `ULID` constraint and validator * added support for UUIDv6 in `Uuid` constraint + * enabled the validator to load constraints from PHP attributes 5.1.0 ----- diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index 31f65f92b9..6381d38273 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -91,9 +91,11 @@ abstract class Constraint * getRequiredOptions() to return the names of these options. If any * option is not set here, an exception is thrown. * - * @param mixed $options The options (as associative array) - * or the value for the default - * option (any other type) + * @param mixed $options The options (as associative array) + * or the value for the default + * option (any other type) + * @param string[] $groups An array of validation groups + * @param mixed $payload Domain-specific data attached to a constraint * * @throws InvalidOptionsException When you pass the names of non-existing * options @@ -103,9 +105,15 @@ abstract class Constraint * array, but getDefaultOption() returns * null */ - public function __construct($options = null) + public function __construct($options = null, array $groups = null, $payload = null) { - foreach ($this->normalizeOptions($options) as $name => $value) { + $options = $this->normalizeOptions($options); + if (null !== $groups) { + $options['groups'] = $groups; + } + $options['payload'] = $payload ?? $options['payload'] ?? null; + + foreach ($options as $name => $value) { $this->$name = $value; } } diff --git a/src/Symfony/Component/Validator/Constraints/Blank.php b/src/Symfony/Component/Validator/Constraints/Blank.php index 4fa913c85f..b0380d996f 100644 --- a/src/Symfony/Component/Validator/Constraints/Blank.php +++ b/src/Symfony/Component/Validator/Constraints/Blank.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Blank extends Constraint { const NOT_BLANK_ERROR = '183ad2de-533d-4796-a439-6d3c3852b549'; @@ -28,4 +29,11 @@ class Blank extends Constraint ]; public $message = 'This value should be blank.'; + + public function __construct(array $options = null, string $message = null, array $groups = null, $payload = null) + { + parent::__construct($options ?? [], $groups, $payload); + + $this->message = $message ?? $this->message; + } } diff --git a/src/Symfony/Component/Validator/Constraints/Callback.php b/src/Symfony/Component/Validator/Constraints/Callback.php index 8bf6d68cac..7b9c3c37c8 100644 --- a/src/Symfony/Component/Validator/Constraints/Callback.php +++ b/src/Symfony/Component/Validator/Constraints/Callback.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Callback extends Constraint { /** @@ -28,19 +29,23 @@ class Callback extends Constraint /** * {@inheritdoc} + * + * @param array|string|callable $callback The callback or a set of options */ - public function __construct($options = null) + public function __construct($callback = null, array $groups = null, $payload = null, array $options = []) { // Invocation through annotations with an array parameter only - if (\is_array($options) && 1 === \count($options) && isset($options['value'])) { - $options = $options['value']; + if (\is_array($callback) && 1 === \count($callback) && isset($callback['value'])) { + $callback = $callback['value']; } - if (\is_array($options) && !isset($options['callback']) && !isset($options['groups']) && !isset($options['payload'])) { - $options = ['callback' => $options]; + if (!\is_array($callback) || (!isset($callback['callback']) && !isset($callback['groups']) && !isset($callback['payload']))) { + $options['callback'] = $callback; + } else { + $options = array_merge($callback, $options); } - parent::__construct($options); + parent::__construct($options, $groups, $payload); } /** diff --git a/src/Symfony/Component/Validator/Constraints/Choice.php b/src/Symfony/Component/Validator/Constraints/Choice.php index 9409491446..0d7a2b7deb 100644 --- a/src/Symfony/Component/Validator/Constraints/Choice.php +++ b/src/Symfony/Component/Validator/Constraints/Choice.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Choice extends Constraint { const NO_SUCH_CHOICE_ERROR = '8e179f1b-97aa-4560-a02f-2a8b42e49df7'; @@ -49,4 +50,38 @@ class Choice extends Constraint { return 'choices'; } + + public function __construct( + $choices = null, + $callback = null, + bool $multiple = null, + bool $strict = null, + int $min = null, + int $max = null, + string $message = null, + string $multipleMessage = null, + string $minMessage = null, + string $maxMessage = null, + $groups = null, + $payload = null, + array $options = [] + ) { + if (\is_array($choices) && \is_string(key($choices))) { + $options = array_merge($choices, $options); + } elseif (null !== $choices) { + $options['choices'] = $choices; + } + + parent::__construct($options, $groups, $payload); + + $this->callback = $callback ?? $this->callback; + $this->multiple = $multiple ?? $this->multiple; + $this->strict = $strict ?? $this->strict; + $this->min = $min ?? $this->min; + $this->max = $max ?? $this->max; + $this->message = $message ?? $this->message; + $this->multipleMessage = $multipleMessage ?? $this->multipleMessage; + $this->minMessage = $minMessage ?? $this->minMessage; + $this->maxMessage = $maxMessage ?? $this->maxMessage; + } } diff --git a/src/Symfony/Component/Validator/Constraints/GroupSequence.php b/src/Symfony/Component/Validator/Constraints/GroupSequence.php index be5bdc4bec..750000d03f 100644 --- a/src/Symfony/Component/Validator/Constraints/GroupSequence.php +++ b/src/Symfony/Component/Validator/Constraints/GroupSequence.php @@ -51,6 +51,7 @@ namespace Symfony\Component\Validator\Constraints; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_CLASS)] class GroupSequence { /** diff --git a/src/Symfony/Component/Validator/Constraints/GroupSequenceProvider.php b/src/Symfony/Component/Validator/Constraints/GroupSequenceProvider.php index 8a3fe6300f..489a449e83 100644 --- a/src/Symfony/Component/Validator/Constraints/GroupSequenceProvider.php +++ b/src/Symfony/Component/Validator/Constraints/GroupSequenceProvider.php @@ -19,6 +19,7 @@ namespace Symfony\Component\Validator\Constraints; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_CLASS)] class GroupSequenceProvider { } diff --git a/src/Symfony/Component/Validator/Constraints/IsFalse.php b/src/Symfony/Component/Validator/Constraints/IsFalse.php index d488c616dd..5885bbd6a2 100644 --- a/src/Symfony/Component/Validator/Constraints/IsFalse.php +++ b/src/Symfony/Component/Validator/Constraints/IsFalse.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class IsFalse extends Constraint { const NOT_FALSE_ERROR = 'd53a91b0-def3-426a-83d7-269da7ab4200'; @@ -28,4 +29,11 @@ class IsFalse extends Constraint ]; public $message = 'This value should be false.'; + + public function __construct(array $options = null, string $message = null, array $groups = null, $payload = null) + { + parent::__construct($options ?? [], $groups, $payload); + + $this->message = $message ?? $this->message; + } } diff --git a/src/Symfony/Component/Validator/Constraints/IsNull.php b/src/Symfony/Component/Validator/Constraints/IsNull.php index e010f9cf06..9a56f7589b 100644 --- a/src/Symfony/Component/Validator/Constraints/IsNull.php +++ b/src/Symfony/Component/Validator/Constraints/IsNull.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class IsNull extends Constraint { const NOT_NULL_ERROR = '60d2f30b-8cfa-4372-b155-9656634de120'; @@ -28,4 +29,11 @@ class IsNull extends Constraint ]; public $message = 'This value should be null.'; + + public function __construct(array $options = null, string $message = null, array $groups = null, $payload = null) + { + parent::__construct($options ?? [], $groups, $payload); + + $this->message = $message ?? $this->message; + } } diff --git a/src/Symfony/Component/Validator/Constraints/IsTrue.php b/src/Symfony/Component/Validator/Constraints/IsTrue.php index 84f6ce15a7..57801acfe8 100644 --- a/src/Symfony/Component/Validator/Constraints/IsTrue.php +++ b/src/Symfony/Component/Validator/Constraints/IsTrue.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class IsTrue extends Constraint { const NOT_TRUE_ERROR = '2beabf1c-54c0-4882-a928-05249b26e23b'; @@ -28,4 +29,11 @@ class IsTrue extends Constraint ]; public $message = 'This value should be true.'; + + public function __construct(array $options = null, string $message = null, array $groups = null, $payload = null) + { + parent::__construct($options ?? [], $groups, $payload); + + $this->message = $message ?? $this->message; + } } diff --git a/src/Symfony/Component/Validator/Constraints/NotBlank.php b/src/Symfony/Component/Validator/Constraints/NotBlank.php index 7e001a3f5f..f25d206b61 100644 --- a/src/Symfony/Component/Validator/Constraints/NotBlank.php +++ b/src/Symfony/Component/Validator/Constraints/NotBlank.php @@ -21,6 +21,7 @@ use Symfony\Component\Validator\Exception\InvalidArgumentException; * @author Bernhard Schussek * @author Kévin Dunglas */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class NotBlank extends Constraint { const IS_BLANK_ERROR = 'c1051bb4-d103-4f74-8988-acbcafc7fdc3'; @@ -33,9 +34,13 @@ class NotBlank extends Constraint public $allowNull = false; public $normalizer; - public function __construct($options = null) + public function __construct(array $options = null, string $message = null, bool $allowNull = null, callable $normalizer = null, array $groups = null, $payload = null) { - parent::__construct($options); + parent::__construct($options ?? [], $groups, $payload); + + $this->message = $message ?? $this->message; + $this->allowNull = $allowNull ?? $this->allowNull; + $this->normalizer = $normalizer ?? $this->normalizer; if (null !== $this->normalizer && !\is_callable($this->normalizer)) { throw new InvalidArgumentException(sprintf('The "normalizer" option must be a valid callable ("%s" given).', get_debug_type($this->normalizer))); diff --git a/src/Symfony/Component/Validator/Constraints/NotNull.php b/src/Symfony/Component/Validator/Constraints/NotNull.php index a392104d0e..1c4e62521c 100644 --- a/src/Symfony/Component/Validator/Constraints/NotNull.php +++ b/src/Symfony/Component/Validator/Constraints/NotNull.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class NotNull extends Constraint { const IS_NULL_ERROR = 'ad32d13f-c3d4-423b-909a-857b961eb720'; @@ -28,4 +29,11 @@ class NotNull extends Constraint ]; public $message = 'This value should not be null.'; + + public function __construct(array $options = null, string $message = null, array $groups = null, $payload = null) + { + parent::__construct($options ?? [], $groups, $payload); + + $this->message = $message ?? $this->message; + } } diff --git a/src/Symfony/Component/Validator/Constraints/Range.php b/src/Symfony/Component/Validator/Constraints/Range.php index 7bbe69fcc3..bc6245152c 100644 --- a/src/Symfony/Component/Validator/Constraints/Range.php +++ b/src/Symfony/Component/Validator/Constraints/Range.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyPathInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\LogicException; @@ -23,6 +24,7 @@ use Symfony\Component\Validator\Exception\MissingOptionsException; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Range extends Constraint { const INVALID_CHARACTERS_ERROR = 'ad9a9798-7a99-4df7-8ce9-46e416a1e60b'; @@ -57,36 +59,62 @@ class Range extends Constraint */ public $deprecatedMaxMessageSet = false; - public function __construct($options = null) - { - if (\is_array($options)) { - if (isset($options['min']) && isset($options['minPropertyPath'])) { - throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires only one of the "min" or "minPropertyPath" options to be set, not both.', static::class)); - } + /** + * {@inheritdoc} + * + * @param string|PropertyPathInterface|null $minPropertyPath + * @param string|PropertyPathInterface|null $maxPropertyPath + */ + public function __construct( + array $options = null, + string $notInRangeMessage = null, + string $minMessage = null, + string $maxMessage = null, + string $invalidMessage = null, + string $invalidDateTimeMessage = null, + $min = null, + $minPropertyPath = null, + $max = null, + $maxPropertyPath = null, + array $groups = null, + $payload = null + ) { + parent::__construct($options, $groups, $payload); - if (isset($options['max']) && isset($options['maxPropertyPath'])) { - throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires only one of the "max" or "maxPropertyPath" options to be set, not both.', static::class)); - } - - if ((isset($options['minPropertyPath']) || isset($options['maxPropertyPath'])) && !class_exists(PropertyAccess::class)) { - throw new LogicException(sprintf('The "%s" constraint requires the Symfony PropertyAccess component to use the "minPropertyPath" or "maxPropertyPath" option.', static::class)); - } - - if (isset($options['min']) && isset($options['max'])) { - $this->deprecatedMinMessageSet = isset($options['minMessage']); - $this->deprecatedMaxMessageSet = isset($options['maxMessage']); - - // BC layer, should throw a ConstraintDefinitionException in 6.0 - if ($this->deprecatedMinMessageSet || $this->deprecatedMaxMessageSet) { - trigger_deprecation('symfony/validator', '4.4', '"minMessage" and "maxMessage" are deprecated when the "min" and "max" options are both set. Use "notInRangeMessage" instead.'); - } - } - } - - parent::__construct($options); + $this->notInRangeMessage = $notInRangeMessage ?? $this->notInRangeMessage; + $this->minMessage = $minMessage ?? $this->minMessage; + $this->maxMessage = $maxMessage ?? $this->maxMessage; + $this->invalidMessage = $invalidMessage ?? $this->invalidMessage; + $this->invalidDateTimeMessage = $invalidDateTimeMessage ?? $this->invalidDateTimeMessage; + $this->min = $min ?? $this->min; + $this->minPropertyPath = $minPropertyPath ?? $this->minPropertyPath; + $this->max = $max ?? $this->max; + $this->maxPropertyPath = $maxPropertyPath ?? $this->maxPropertyPath; if (null === $this->min && null === $this->minPropertyPath && null === $this->max && null === $this->maxPropertyPath) { throw new MissingOptionsException(sprintf('Either option "min", "minPropertyPath", "max" or "maxPropertyPath" must be given for constraint "%s".', __CLASS__), ['min', 'minPropertyPath', 'max', 'maxPropertyPath']); } + + if (null !== $this->min && null !== $this->minPropertyPath) { + throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires only one of the "min" or "minPropertyPath" options to be set, not both.', static::class)); + } + + if (null !== $this->max && null !== $this->maxPropertyPath) { + throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires only one of the "max" or "maxPropertyPath" options to be set, not both.', static::class)); + } + + if ((null !== $this->minPropertyPath || null !== $this->maxPropertyPath) && !class_exists(PropertyAccess::class)) { + throw new LogicException(sprintf('The "%s" constraint requires the Symfony PropertyAccess component to use the "minPropertyPath" or "maxPropertyPath" option.', static::class)); + } + + if (null !== $this->min && null !== $this->max) { + $this->deprecatedMinMessageSet = isset($options['minMessage']) || null !== $minMessage; + $this->deprecatedMaxMessageSet = isset($options['maxMessage']) || null !== $maxMessage; + + // BC layer, should throw a ConstraintDefinitionException in 6.0 + if ($this->deprecatedMinMessageSet || $this->deprecatedMaxMessageSet) { + trigger_deprecation('symfony/validator', '4.4', '"minMessage" and "maxMessage" are deprecated when the "min" and "max" options are both set. Use "notInRangeMessage" instead.'); + } + } } } diff --git a/src/Symfony/Component/Validator/Constraints/Valid.php b/src/Symfony/Component/Validator/Constraints/Valid.php index 6d276e0729..312ab88448 100644 --- a/src/Symfony/Component/Validator/Constraints/Valid.php +++ b/src/Symfony/Component/Validator/Constraints/Valid.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraint; * * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Valid extends Constraint { public $traverse = true; diff --git a/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php index b60e0afbef..cbb324e24e 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/AnnotationLoader.php @@ -23,12 +23,13 @@ use Symfony\Component\Validator\Mapping\ClassMetadata; * Loads validation metadata using a Doctrine annotation {@link Reader}. * * @author Bernhard Schussek + * @author Alexander M. Turek */ class AnnotationLoader implements LoaderInterface { protected $reader; - public function __construct(Reader $reader) + public function __construct(Reader $reader = null) { $this->reader = $reader; } @@ -42,7 +43,7 @@ class AnnotationLoader implements LoaderInterface $className = $reflClass->name; $success = false; - foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) { + foreach ($this->getAnnotations($reflClass) as $constraint) { if ($constraint instanceof GroupSequence) { $metadata->setGroupSequence($constraint->groups); } elseif ($constraint instanceof GroupSequenceProvider) { @@ -56,7 +57,7 @@ class AnnotationLoader implements LoaderInterface foreach ($reflClass->getProperties() as $property) { if ($property->getDeclaringClass()->name === $className) { - foreach ($this->reader->getPropertyAnnotations($property) as $constraint) { + foreach ($this->getAnnotations($property) as $constraint) { if ($constraint instanceof Constraint) { $metadata->addPropertyConstraint($property->name, $constraint); } @@ -68,7 +69,7 @@ class AnnotationLoader implements LoaderInterface foreach ($reflClass->getMethods() as $method) { if ($method->getDeclaringClass()->name === $className) { - foreach ($this->reader->getMethodAnnotations($method) as $constraint) { + foreach ($this->getAnnotations($method) as $constraint) { if ($constraint instanceof Callback) { $constraint->callback = $method->getName(); @@ -88,4 +89,35 @@ class AnnotationLoader implements LoaderInterface return $success; } + + /** + * @param \ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflection + */ + private function getAnnotations(object $reflection): iterable + { + if (\PHP_VERSION_ID >= 80000) { + foreach ($reflection->getAttributes(GroupSequence::class) as $attribute) { + yield $attribute->newInstance(); + } + foreach ($reflection->getAttributes(GroupSequenceProvider::class) as $attribute) { + yield $attribute->newInstance(); + } + foreach ($reflection->getAttributes(Constraint::class, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { + yield $attribute->newInstance(); + } + } + if (!$this->reader) { + return; + } + + if ($reflection instanceof \ReflectionClass) { + yield from $this->reader->getClassAnnotations($reflection); + } + if ($reflection instanceof \ReflectionMethod) { + yield from $this->reader->getMethodAnnotations($reflection); + } + if ($reflection instanceof \ReflectionProperty) { + yield from $this->reader->getPropertyAnnotations($reflection); + } + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php index 4e712b92ad..86a1af88da 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CallbackValidatorTest.php @@ -229,22 +229,29 @@ class CallbackValidatorTest extends ConstraintValidatorTestCase public function testPayloadIsPassedToCallback() { $object = new \stdClass(); - $payloadCopy = null; + $payloadCopy = 'Replace me!'; + $callback = function ($object, ExecutionContextInterface $constraint, $payload) use (&$payloadCopy) { + $payloadCopy = $payload; + }; $constraint = new Callback([ - 'callback' => function ($object, ExecutionContextInterface $constraint, $payload) use (&$payloadCopy) { - $payloadCopy = $payload; - }, + 'callback' => $callback, 'payload' => 'Hello world!', ]); $this->validator->validate($object, $constraint); $this->assertEquals('Hello world!', $payloadCopy); - $payloadCopy = null; + if (\PHP_VERSION_ID >= 80000) { + $payloadCopy = 'Replace me!'; + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Callback(callback: $callback, payload: "Hello world!");'); + $this->validator->validate($object, $constraint); + $this->assertEquals('Hello world!', $payloadCopy); + $payloadCopy = 'Replace me!'; + } + + $payloadCopy = 'Replace me!'; $constraint = new Callback([ - 'callback' => function ($object, ExecutionContextInterface $constraint, $payload) use (&$payloadCopy) { - $payloadCopy = $payload; - }, + 'callback' => $callback, ]); $this->validator->validate($object, $constraint); $this->assertNull($payloadCopy); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php index c9fb882db3..b8571c5f81 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php @@ -72,44 +72,52 @@ class ChoiceValidatorTest extends ConstraintValidatorTestCase $this->validator->validate('foobar', new Choice(['callback' => 'abcd'])); } - public function testValidChoiceArray() + /** + * @dataProvider provideConstraintsWithChoicesArray + */ + public function testValidChoiceArray(Choice $constraint) { - $constraint = new Choice(['choices' => ['foo', 'bar']]); - $this->validator->validate('bar', $constraint); $this->assertNoViolation(); } - public function testValidChoiceCallbackFunction() + public function provideConstraintsWithChoicesArray(): iterable { - $constraint = new Choice(['callback' => __NAMESPACE__.'\choice_callback']); + yield 'Doctrine style' => [new Choice(['choices' => ['foo', 'bar']])]; + yield 'Doctrine default option' => [new Choice(['value' => ['foo', 'bar']])]; + yield 'first argument' => [new Choice(['foo', 'bar'])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [eval('return new \Symfony\Component\Validator\Constraints\Choice(choices: ["foo", "bar"]);')]; + } + } + + /** + * @dataProvider provideConstraintsWithCallbackFunction + */ + public function testValidChoiceCallbackFunction(Choice $constraint) + { $this->validator->validate('bar', $constraint); $this->assertNoViolation(); } - public function testValidChoiceCallbackClosure() + public function provideConstraintsWithCallbackFunction(): iterable { - $constraint = new Choice([ + yield 'doctrine style, namespaced function' => [new Choice(['callback' => __NAMESPACE__.'\choice_callback'])]; + yield 'doctrine style, closure' => [new Choice([ 'callback' => function () { return ['foo', 'bar']; }, - ]); + ])]; + yield 'doctrine style, static method' => [new Choice(['callback' => [__CLASS__, 'staticCallback']])]; - $this->validator->validate('bar', $constraint); - - $this->assertNoViolation(); - } - - public function testValidChoiceCallbackStaticMethod() - { - $constraint = new Choice(['callback' => [__CLASS__, 'staticCallback']]); - - $this->validator->validate('bar', $constraint); - - $this->assertNoViolation(); + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments, namespaced function' => [eval("return new \Symfony\Component\Validator\Constraints\Choice(callback: 'Symfony\Component\Validator\Tests\Constraints\choice_callback');")]; + yield 'named arguments, closure' => [eval('return new \Symfony\Component\Validator\Constraints\Choice(callback: fn () => ["foo", "bar"]);')]; + yield 'named arguments, static method' => [eval('return new \Symfony\Component\Validator\Constraints\Choice(callback: ["Symfony\Component\Validator\Tests\Constraints\ChoiceValidatorTest", "staticCallback"]);')]; + } } public function testValidChoiceCallbackContextMethod() @@ -136,25 +144,36 @@ class ChoiceValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } - public function testMultipleChoices() + /** + * @dataProvider provideConstraintsWithMultipleTrue + */ + public function testMultipleChoices(Choice $constraint) { - $constraint = new Choice([ - 'choices' => ['foo', 'bar', 'baz'], - 'multiple' => true, - ]); - $this->validator->validate(['baz', 'bar'], $constraint); $this->assertNoViolation(); } - public function testInvalidChoice() + public function provideConstraintsWithMultipleTrue(): iterable { - $constraint = new Choice([ - 'choices' => ['foo', 'bar'], - 'message' => 'myMessage', - ]); + yield 'Doctrine style' => [new Choice([ + 'choices' => ['foo', 'bar', 'baz'], + 'multiple' => true, + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [eval("return new \Symfony\Component\Validator\Constraints\Choice( + choices: ['foo', 'bar', 'baz'], + multiple: true, + );")]; + } + } + + /** + * @dataProvider provideConstraintsWithMessage + */ + public function testInvalidChoice(Choice $constraint) + { $this->validator->validate('baz', $constraint); $this->buildViolation('myMessage') @@ -164,6 +183,15 @@ class ChoiceValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + public function provideConstraintsWithMessage(): iterable + { + yield 'Doctrine style' => [new Choice(['choices' => ['foo', 'bar'], 'message' => 'myMessage'])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [eval('return new \Symfony\Component\Validator\Constraints\Choice(choices: ["foo", "bar"], message: "myMessage");')]; + } + } + public function testInvalidChoiceEmptyChoices() { $constraint = new Choice([ @@ -182,14 +210,11 @@ class ChoiceValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testInvalidChoiceMultiple() + /** + * @dataProvider provideConstraintsWithMultipleMessage + */ + public function testInvalidChoiceMultiple(Choice $constraint) { - $constraint = new Choice([ - 'choices' => ['foo', 'bar'], - 'multipleMessage' => 'myMessage', - 'multiple' => true, - ]); - $this->validator->validate(['foo', 'baz'], $constraint); $this->buildViolation('myMessage') @@ -200,15 +225,28 @@ class ChoiceValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testTooFewChoices() + public function provideConstraintsWithMultipleMessage(): iterable { - $constraint = new Choice([ - 'choices' => ['foo', 'bar', 'moo', 'maa'], + yield 'Doctrine style' => [new Choice([ + 'choices' => ['foo', 'bar'], + 'multipleMessage' => 'myMessage', 'multiple' => true, - 'min' => 2, - 'minMessage' => 'myMessage', - ]); + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [eval("return new \Symfony\Component\Validator\Constraints\Choice( + choices: ['foo', 'bar'], + multipleMessage: 'myMessage', + multiple: true, + );")]; + } + } + + /** + * @dataProvider provideConstraintsWithMin + */ + public function testTooFewChoices(Choice $constraint) + { $value = ['foo']; $this->setValue($value); @@ -223,15 +261,30 @@ class ChoiceValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } - public function testTooManyChoices() + public function provideConstraintsWithMin(): iterable { - $constraint = new Choice([ + yield 'Doctrine style' => [new Choice([ 'choices' => ['foo', 'bar', 'moo', 'maa'], 'multiple' => true, - 'max' => 2, - 'maxMessage' => 'myMessage', - ]); + 'min' => 2, + 'minMessage' => 'myMessage', + ])]; + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [eval("return new \Symfony\Component\Validator\Constraints\Choice( + choices: ['foo', 'bar', 'moo', 'maa'], + multiple: true, + min: 2, + minMessage: 'myMessage', + );")]; + } + } + + /** + * @dataProvider provideConstraintsWithMax + */ + public function testTooManyChoices(Choice $constraint) + { $value = ['foo', 'bar', 'moo']; $this->setValue($value); @@ -246,6 +299,25 @@ class ChoiceValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + public function provideConstraintsWithMax(): iterable + { + yield 'Doctrine style' => [new Choice([ + 'choices' => ['foo', 'bar', 'moo', 'maa'], + 'multiple' => true, + 'max' => 2, + 'maxMessage' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'named arguments' => [eval("return new \Symfony\Component\Validator\Constraints\Choice( + choices: ['foo', 'bar', 'moo', 'maa'], + multiple: true, + max: 2, + maxMessage: 'myMessage', + );")]; + } + } + public function testStrictAllowsExactValue() { $constraint = new Choice([ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php index 280757b8e9..8dee586dc3 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionValidatorTest.php @@ -15,7 +15,7 @@ use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\ExpressionValidator; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; -use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; use Symfony\Component\Validator\Tests\Fixtures\ToString; class ExpressionValidatorTest extends ConstraintValidatorTestCase diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IsFalseValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IsFalseValidatorTest.php index 65aecf94be..1ec75dcb84 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IsFalseValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IsFalseValidatorTest.php @@ -36,12 +36,11 @@ class IsFalseValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } - public function testTrueIsInvalid() + /** + * @dataProvider provideInvalidConstraints + */ + public function testTrueIsInvalid(IsFalse $constraint) { - $constraint = new IsFalse([ - 'message' => 'myMessage', - ]); - $this->validator->validate(true, $constraint); $this->buildViolation('myMessage') @@ -49,4 +48,15 @@ class IsFalseValidatorTest extends ConstraintValidatorTestCase ->setCode(IsFalse::NOT_FALSE_ERROR) ->assertRaised(); } + + public function provideInvalidConstraints(): iterable + { + yield 'Doctrine style' => [new IsFalse([ + 'message' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'named parameters' => [eval('return new \Symfony\Component\Validator\Constraints\IsFalse(message: "myMessage");')]; + } + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IsNullValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IsNullValidatorTest.php index 60f9e95f47..f3128eb23e 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IsNullValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IsNullValidatorTest.php @@ -46,6 +46,22 @@ class IsNullValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + * @dataProvider getInvalidValues + */ + public function testInvalidValuesNamed($value, $valueAsString) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\IsNull(message: "myMessage");'); + + $this->validator->validate($value, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', $valueAsString) + ->setCode(IsNull::NOT_NULL_ERROR) + ->assertRaised(); + } + public function getInvalidValues() { return [ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IsTrueValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IsTrueValidatorTest.php index e3e0c52b93..e12cbdde3f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IsTrueValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IsTrueValidatorTest.php @@ -36,12 +36,11 @@ class IsTrueValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } - public function testFalseIsInvalid() + /** + * @dataProvider provideInvalidConstraints + */ + public function testFalseIsInvalid(IsTrue $constraint) { - $constraint = new IsTrue([ - 'message' => 'myMessage', - ]); - $this->validator->validate(false, $constraint); $this->buildViolation('myMessage') @@ -49,4 +48,15 @@ class IsTrueValidatorTest extends ConstraintValidatorTestCase ->setCode(IsTrue::NOT_TRUE_ERROR) ->assertRaised(); } + + public function provideInvalidConstraints(): iterable + { + yield 'Doctrine style' => [new IsTrue([ + 'message' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'named parameters' => [eval('return new \Symfony\Component\Validator\Constraints\IsTrue(message: "myMessage");')]; + } + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php index 285132a1f1..f4781f1577 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotBlankTest.php @@ -13,6 +13,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; /** * @author Renan Taranto @@ -26,6 +28,25 @@ class NotBlankTest extends TestCase $this->assertEquals('trim', $notBlank->normalizer); } + /** + * @requires PHP 8 + */ + public function testAttributes() + { + $metadata = new ClassMetadata(NotBlankDummy::class); + $loader = new AnnotationLoader(); + self::assertTrue($loader->loadClassMetadata($metadata)); + + list($aConstraint) = $metadata->properties['a']->getConstraints(); + self::assertFalse($aConstraint->allowNull); + self::assertNull($aConstraint->normalizer); + + list($bConstraint) = $metadata->properties['b']->getConstraints(); + self::assertTrue($bConstraint->allowNull); + self::assertSame('trim', $bConstraint->normalizer); + self::assertSame('myMessage', $bConstraint->message); + } + public function testInvalidNormalizerThrowsException() { $this->expectException('Symfony\Component\Validator\Exception\InvalidArgumentException'); @@ -40,3 +61,12 @@ class NotBlankTest extends TestCase new NotBlank(['normalizer' => new \stdClass()]); } } + +class NotBlankDummy +{ + #[NotBlank] + private $a; + + #[NotBlank(normalizer: 'trim', allowNull: true, message: 'myMessage')] + private $b; +} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php index a726d063b9..abaa7f874a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotNullValidatorTest.php @@ -42,12 +42,11 @@ class NotNullValidatorTest extends ConstraintValidatorTestCase ]; } - public function testNullIsInvalid() + /** + * @dataProvider provideInvalidConstraints + */ + public function testNullIsInvalid(NotNull $constraint) { - $constraint = new NotNull([ - 'message' => 'myMessage', - ]); - $this->validator->validate(null, $constraint); $this->buildViolation('myMessage') @@ -55,4 +54,15 @@ class NotNullValidatorTest extends ConstraintValidatorTestCase ->setCode(NotNull::IS_NULL_ERROR) ->assertRaised(); } + + public function provideInvalidConstraints(): iterable + { + yield 'Doctrine style' => [new NotNull([ + 'message' => 'myMessage', + ])]; + + if (\PHP_VERSION_ID >= 80000) { + yield 'named parameters' => [eval('return new \Symfony\Component\Validator\Constraints\NotNull(message: "myMessage");')]; + } + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/RangeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/RangeTest.php index f89b5c1f7c..94c3ef75f2 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/RangeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/RangeTest.php @@ -20,6 +20,16 @@ class RangeTest extends TestCase ]); } + /** + * @requires PHP 8 + */ + public function testThrowsConstraintExceptionIfBothMinLimitAndPropertyPathNamed() + { + $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); + $this->expectExceptionMessage('requires only one of the "min" or "minPropertyPath" options to be set, not both.'); + eval('new \Symfony\Component\Validator\Constraints\Range(min: "min", minPropertyPath: "minPropertyPath");'); + } + public function testThrowsConstraintExceptionIfBothMaxLimitAndPropertyPath() { $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); @@ -30,6 +40,16 @@ class RangeTest extends TestCase ]); } + /** + * @requires PHP 8 + */ + public function testThrowsConstraintExceptionIfBothMaxLimitAndPropertyPathNamed() + { + $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); + $this->expectExceptionMessage('requires only one of the "max" or "maxPropertyPath" options to be set, not both.'); + eval('new \Symfony\Component\Validator\Constraints\Range(max: "max", maxPropertyPath: "maxPropertyPath");'); + } + public function testThrowsConstraintExceptionIfNoLimitNorPropertyPath() { $this->expectException('Symfony\Component\Validator\Exception\MissingOptionsException'); @@ -39,8 +59,7 @@ class RangeTest extends TestCase public function testThrowsNoDefaultOptionConfiguredException() { - $this->expectException('Symfony\Component\Validator\Exception\ConstraintDefinitionException'); - $this->expectExceptionMessage('No default option is configured'); + $this->expectException(\TypeError::class); new Range('value'); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php index 3d7a773a21..7a34810bdf 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php @@ -76,6 +76,18 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } + /** + * @requires PHP 8 + * @dataProvider getTenToTwenty + */ + public function testValidValuesMinNamed($value) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range(min: 10);'); + $this->validator->validate($value, $constraint); + + $this->assertNoViolation(); + } + /** * @dataProvider getTenToTwenty */ @@ -87,6 +99,18 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } + /** + * @requires PHP 8 + * @dataProvider getTenToTwenty + */ + public function testValidValuesMaxNamed($value) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range(max: 20);'); + $this->validator->validate($value, $constraint); + + $this->assertNoViolation(); + } + /** * @dataProvider getTenToTwenty */ @@ -98,6 +122,18 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } + /** + * @requires PHP 8 + * @dataProvider getTenToTwenty + */ + public function testValidValuesMinMaxNamed($value) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range(min:10, max: 20);'); + $this->validator->validate($value, $constraint); + + $this->assertNoViolation(); + } + /** * @dataProvider getLessThanTen */ @@ -117,6 +153,23 @@ class RangeValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + * @dataProvider getLessThanTen + */ + public function testInvalidValuesMinNamed($value, $formattedValue) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range(min:10, minMessage: "myMessage");'); + + $this->validator->validate($value, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', $formattedValue) + ->setParameter('{{ limit }}', 10) + ->setCode(Range::TOO_LOW_ERROR) + ->assertRaised(); + } + /** * @dataProvider getMoreThanTwenty */ @@ -136,6 +189,23 @@ class RangeValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + * @dataProvider getMoreThanTwenty + */ + public function testInvalidValuesMaxNamed($value, $formattedValue) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range(max:20, maxMessage: "myMessage");'); + + $this->validator->validate($value, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', $formattedValue) + ->setParameter('{{ limit }}', 20) + ->setCode(Range::TOO_HIGH_ERROR) + ->assertRaised(); + } + /** * @dataProvider getMoreThanTwenty */ @@ -157,6 +227,24 @@ class RangeValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + * @dataProvider getMoreThanTwenty + */ + public function testInvalidValuesCombinedMaxNamed($value, $formattedValue) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range(min: 10, max:20, notInRangeMessage: "myNotInRangeMessage");'); + + $this->validator->validate($value, $constraint); + + $this->buildViolation('myNotInRangeMessage') + ->setParameter('{{ value }}', $formattedValue) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) + ->setCode(Range::NOT_IN_RANGE_ERROR) + ->assertRaised(); + } + /** * @dataProvider getLessThanTen */ @@ -178,6 +266,24 @@ class RangeValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + * @dataProvider getLessThanTen + */ + public function testInvalidValuesCombinedMinNamed($value, $formattedValue) + { + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range(min: 10, max:20, notInRangeMessage: "myNotInRangeMessage");'); + + $this->validator->validate($value, $constraint); + + $this->buildViolation('myNotInRangeMessage') + ->setParameter('{{ value }}', $formattedValue) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) + ->setCode(Range::NOT_IN_RANGE_ERROR) + ->assertRaised(); + } + public function getTenthToTwentiethMarch2014() { // The provider runs before setUp(), so we need to manually fix @@ -531,6 +637,19 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } + /** + * @requires PHP 8 + * @dataProvider getTenToTwenty + */ + public function testValidValuesMinPropertyPathNamed($value) + { + $this->setObject(new Limit(10)); + + $this->validator->validate($value, eval('return new \Symfony\Component\Validator\Constraints\Range(minPropertyPath: "value");')); + + $this->assertNoViolation(); + } + /** * @dataProvider getTenToTwenty */ @@ -545,6 +664,19 @@ class RangeValidatorTest extends ConstraintValidatorTestCase $this->assertNoViolation(); } + /** + * @requires PHP 8 + * @dataProvider getTenToTwenty + */ + public function testValidValuesMaxPropertyPathNamed($value) + { + $this->setObject(new Limit(20)); + + $this->validator->validate($value, eval('return new \Symfony\Component\Validator\Constraints\Range(maxPropertyPath: "value");')); + + $this->assertNoViolation(); + } + /** * @dataProvider getTenToTwenty */ @@ -629,6 +761,32 @@ class RangeValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + * @dataProvider getMoreThanTwenty + */ + public function testInvalidValuesCombinedMaxPropertyPathNamed($value, $formattedValue) + { + $this->setObject(new MinMax(10, 20)); + + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range( + minPropertyPath: "min", + maxPropertyPath: "max", + notInRangeMessage: "myNotInRangeMessage", + );'); + + $this->validator->validate($value, $constraint); + + $this->buildViolation('myNotInRangeMessage') + ->setParameter('{{ value }}', $formattedValue) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) + ->setParameter('{{ max_limit_path }}', 'max') + ->setParameter('{{ min_limit_path }}', 'min') + ->setCode(Range::NOT_IN_RANGE_ERROR) + ->assertRaised(); + } + /** * @dataProvider getLessThanTen */ @@ -654,6 +812,32 @@ class RangeValidatorTest extends ConstraintValidatorTestCase ->assertRaised(); } + /** + * @requires PHP 8 + * @dataProvider getLessThanTen + */ + public function testInvalidValuesCombinedMinPropertyPathNamed($value, $formattedValue) + { + $this->setObject(new MinMax(10, 20)); + + $constraint = eval('return new \Symfony\Component\Validator\Constraints\Range( + minPropertyPath: "min", + maxPropertyPath: "max", + notInRangeMessage: "myNotInRangeMessage", + );'); + + $this->validator->validate($value, $constraint); + + $this->buildViolation('myNotInRangeMessage') + ->setParameter('{{ value }}', $formattedValue) + ->setParameter('{{ min }}', 10) + ->setParameter('{{ max }}', 20) + ->setParameter('{{ max_limit_path }}', 'max') + ->setParameter('{{ min_limit_path }}', 'min') + ->setCode(Range::NOT_IN_RANGE_ERROR) + ->assertRaised(); + } + /** * @dataProvider getLessThanTen */ diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php b/src/Symfony/Component/Validator/Tests/Fixtures/Annotation/Entity.php similarity index 95% rename from src/Symfony/Component/Validator/Tests/Fixtures/Entity.php rename to src/Symfony/Component/Validator/Tests/Fixtures/Annotation/Entity.php index 673e62bae7..c818062f56 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/Entity.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Annotation/Entity.php @@ -9,10 +9,11 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Validator\Tests\Fixtures; +namespace Symfony\Component\Validator\Tests\Fixtures\Annotation; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceB; /** * @Symfony\Component\Validator\Tests\Fixtures\ConstraintA diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php b/src/Symfony/Component/Validator/Tests/Fixtures/Annotation/EntityParent.php similarity index 83% rename from src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php rename to src/Symfony/Component/Validator/Tests/Fixtures/Annotation/EntityParent.php index eb09e5a4b2..497100ef8b 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/EntityParent.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Annotation/EntityParent.php @@ -9,9 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Validator\Tests\Fixtures; +namespace Symfony\Component\Validator\Tests\Fixtures\Annotation; use Symfony\Component\Validator\Constraints\NotNull; +use Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceA; class EntityParent implements EntityInterfaceA { diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php b/src/Symfony/Component/Validator/Tests/Fixtures/Annotation/GroupSequenceProviderEntity.php similarity index 91% rename from src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php rename to src/Symfony/Component/Validator/Tests/Fixtures/Annotation/GroupSequenceProviderEntity.php index 77b3bf2f7b..59448c1bc6 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderEntity.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Annotation/GroupSequenceProviderEntity.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Validator\Tests\Fixtures; +namespace Symfony\Component\Validator\Tests\Fixtures\Annotation; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\Validator\GroupSequenceProviderInterface; diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/Entity.php b/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/Entity.php new file mode 100644 index 0000000000..c4b2a7a883 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/Entity.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures\Attribute; + +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceB; +use Symfony\Component\Validator\Tests\Fixtures\CallbackClass; +use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; + +#[ + ConstraintA, + Assert\GroupSequence(['Foo', 'Entity']), + Assert\Callback([CallbackClass::class, 'callback']), +] +class Entity extends EntityParent implements EntityInterfaceB +{ + /** + * @Assert\All({@Assert\NotNull, @Assert\Range(min=3)}), + * @Assert\All(constraints={@Assert\NotNull, @Assert\Range(min=3)}) + * @Assert\Collection(fields={ + * "foo" = {@Assert\NotNull, @Assert\Range(min=3)}, + * "bar" = @Assert\Range(min=5) + * }) + * @Assert\Choice(choices={"A", "B"}, message="Must be one of %choices%") + */ + #[ + Assert\NotNull, + Assert\Range(min: 3), + ] + public $firstName; + #[Assert\Valid] + public $childA; + #[Assert\Valid] + public $childB; + protected $lastName; + public $reference; + public $reference2; + private $internal; + public $data = 'Overridden data'; + public $initialized = false; + + public function __construct($internal = null) + { + $this->internal = $internal; + } + + public function getFirstName() + { + return $this->firstName; + } + + public function getInternal() + { + return $this->internal.' from getter'; + } + + public function setLastName($lastName) + { + $this->lastName = $lastName; + } + + #[Assert\NotNull] + public function getLastName() + { + return $this->lastName; + } + + public function getValid() + { + } + + #[Assert\IsTrue] + public function isValid() + { + return 'valid'; + } + + #[Assert\IsTrue] + public function hasPermissions() + { + return 'permissions'; + } + + public function getData() + { + return 'Overridden data'; + } + + #[Assert\Callback(payload: 'foo')] + public function validateMe(ExecutionContextInterface $context) + { + } + + #[Assert\Callback] + public static function validateMeStatic($object, ExecutionContextInterface $context) + { + } + + /** + * @return mixed + */ + public function getChildA() + { + return $this->childA; + } + + /** + * @param mixed $childA + */ + public function setChildA($childA) + { + $this->childA = $childA; + } + + /** + * @return mixed + */ + public function getChildB() + { + return $this->childB; + } + + /** + * @param mixed $childB + */ + public function setChildB($childB) + { + $this->childB = $childB; + } + + public function getReference() + { + return $this->reference; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/EntityParent.php b/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/EntityParent.php new file mode 100644 index 0000000000..e595f82d04 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/EntityParent.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures\Attribute; + +use Symfony\Component\Validator\Constraints\NotNull; +use Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceA; + +class EntityParent implements EntityInterfaceA +{ + protected $firstName; + private $internal; + private $data = 'Data'; + private $child; + + #[NotNull] + protected $other; + + public function getData() + { + return 'Data'; + } + + public function getChild() + { + return $this->child; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/GroupSequenceProviderEntity.php b/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/GroupSequenceProviderEntity.php new file mode 100644 index 0000000000..f3c5230224 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Attribute/GroupSequenceProviderEntity.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures\Attribute; + +use Symfony\Component\Validator\Constraints as Assert; +use Symfony\Component\Validator\GroupSequenceProviderInterface; + +#[Assert\GroupSequenceProvider] +class GroupSequenceProviderEntity implements GroupSequenceProviderInterface +{ + public $firstName; + public $lastName; + + protected $sequence = []; + + public function __construct($sequence) + { + $this->sequence = $sequence; + } + + public function getGroupSequence() + { + return $this->sequence; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php b/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php index 7c2fea8751..d2e559f5a2 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/ConstraintA.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Tests\Fixtures; use Symfony\Component\Validator\Constraint; /** @Annotation */ +#[\Attribute] class ConstraintA extends Constraint { public $property1; diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php b/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php index be7191f9b6..ee8f718748 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Fixtures; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; + class GroupSequenceProviderChildEntity extends GroupSequenceProviderEntity { } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php index 90133f75e4..44218fde1d 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php @@ -19,6 +19,9 @@ use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Mapping\CascadingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\EntityParent; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity; use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; @@ -27,9 +30,9 @@ use Symfony\Component\Validator\Tests\Fixtures\PropertyConstraint; class ClassMetadataTest extends TestCase { - const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; - const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; - const PROVIDERCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'; + const CLASSNAME = Entity::class; + const PARENTCLASS = EntityParent::class; + const PROVIDERCLASS = GroupSequenceProviderEntity::class; const PROVIDERCHILDCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderChildEntity'; protected $metadata; diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php index 14709fb857..dde0dcc0d7 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php @@ -19,14 +19,16 @@ use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\EntityParent; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\PropertyGetter; use Symfony\Component\Validator\Tests\Fixtures\PropertyGetterInterface; class LazyLoadingMetadataFactoryTest extends TestCase { - const CLASS_NAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; - const PARENT_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; + const CLASS_NAME = Entity::class; + const PARENT_CLASS = EntityParent::class; const INTERFACE_A_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceA'; const INTERFACE_B_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityInterfaceB'; const PARENT_INTERFACE_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParentInterface'; diff --git a/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php index 127bd5a164..cc188f07ac 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/GetterMetadataTest.php @@ -13,11 +13,11 @@ namespace Symfony\Component\Validator\Tests\Mapping; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Mapping\GetterMetadata; -use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; class GetterMetadataTest extends TestCase { - const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; + const CLASSNAME = Entity::class; public function testInvalidPropertyName() { @@ -64,7 +64,7 @@ class GetterMetadataTest extends TestCase public function testUndefinedMethodNameThrowsException() { $this->expectException('Symfony\Component\Validator\Exception\ValidatorException'); - $this->expectExceptionMessage('The "hasLastName()" method does not exist in class "Symfony\Component\Validator\Tests\Fixtures\Entity".'); + $this->expectExceptionMessage('The "hasLastName()" method does not exist in class "Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity".'); new GetterMetadata(self::CLASSNAME, 'lastName', 'hasLastName'); } } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php index e500962429..e59bfd0e6e 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/AnnotationLoaderTest.php @@ -23,6 +23,7 @@ use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; class AnnotationLoaderTest extends TestCase @@ -31,7 +32,7 @@ class AnnotationLoaderTest extends TestCase { $reader = new AnnotationReader(); $loader = new AnnotationLoader($reader); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $this->assertTrue($loader->loadClassMetadata($metadata)); } @@ -44,14 +45,17 @@ class AnnotationLoaderTest extends TestCase $this->assertFalse($loader->loadClassMetadata($metadata)); } - public function testLoadClassMetadata() + /** + * @dataProvider provideNamespaces + */ + public function testLoadClassMetadata(string $namespace) { $loader = new AnnotationLoader(new AnnotationReader()); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata($namespace.'\Entity'); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $expected = new ClassMetadata($namespace.'\Entity'); $expected->setGroupSequence(['Foo', 'Entity']); $expected->addConstraint(new ConstraintA()); $expected->addConstraint(new Callback(['Symfony\Component\Validator\Tests\Fixtures\CallbackClass', 'callback'])); @@ -83,16 +87,18 @@ class AnnotationLoaderTest extends TestCase /** * Test MetaData merge with parent annotation. + * + * @dataProvider provideNamespaces */ - public function testLoadParentClassMetadata() + public function testLoadParentClassMetadata(string $namespace) { $loader = new AnnotationLoader(new AnnotationReader()); // Load Parent MetaData - $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); + $parent_metadata = new ClassMetadata($namespace.'\EntityParent'); $loader->loadClassMetadata($parent_metadata); - $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); + $expected_parent = new ClassMetadata($namespace.'\EntityParent'); $expected_parent->addPropertyConstraint('other', new NotNull()); $expected_parent->getReflectionClass(); @@ -101,27 +107,29 @@ class AnnotationLoaderTest extends TestCase /** * Test MetaData merge with parent annotation. + * + * @dataProvider provideNamespaces */ - public function testLoadClassMetadataAndMerge() + public function testLoadClassMetadataAndMerge(string $namespace) { $loader = new AnnotationLoader(new AnnotationReader()); // Load Parent MetaData - $parent_metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); + $parent_metadata = new ClassMetadata($namespace.'\EntityParent'); $loader->loadClassMetadata($parent_metadata); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata($namespace.'\Entity'); // Merge parent metaData. $metadata->mergeConstraints($parent_metadata); $loader->loadClassMetadata($metadata); - $expected_parent = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\EntityParent'); + $expected_parent = new ClassMetadata($namespace.'\EntityParent'); $expected_parent->addPropertyConstraint('other', new NotNull()); $expected_parent->getReflectionClass(); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $expected = new ClassMetadata($namespace.'\Entity'); $expected->mergeConstraints($expected_parent); $expected->setGroupSequence(['Foo', 'Entity']); @@ -153,17 +161,29 @@ class AnnotationLoaderTest extends TestCase $this->assertEquals($expected, $metadata); } - public function testLoadGroupSequenceProviderAnnotation() + /** + * @dataProvider provideNamespaces + */ + public function testLoadGroupSequenceProviderAnnotation(string $namespace) { $loader = new AnnotationLoader(new AnnotationReader()); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); + $metadata = new ClassMetadata($namespace.'\GroupSequenceProviderEntity'); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); + $expected = new ClassMetadata($namespace.'\GroupSequenceProviderEntity'); $expected->setGroupSequenceProvider(true); $expected->getReflectionClass(); $this->assertEquals($expected, $metadata); } + + public function provideNamespaces(): iterable + { + yield 'annotations' => ['Symfony\Component\Validator\Tests\Fixtures\Annotation']; + + if (\PHP_VERSION_ID >= 80000) { + yield 'attributes' => ['Symfony\Component\Validator\Tests\Fixtures\Attribute']; + } + } } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php index 2cf009fc08..641aa977c1 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/FilesLoaderTest.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Tests\Mapping\Loader; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\LoaderInterface; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; class FilesLoaderTest extends TestCase { @@ -29,7 +30,7 @@ class FilesLoaderTest extends TestCase $fileLoader->expects($this->exactly(4)) ->method('loadClassMetadata'); $loader = $this->getFilesLoader($fileLoader); - $loader->loadClassMetadata(new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity')); + $loader->loadClassMetadata(new ClassMetadata(Entity::class)); } public function getFilesLoader(LoaderInterface $loader) diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php index 9ae66ca980..c1f147a802 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/PropertyInfoLoaderTest.php @@ -23,7 +23,7 @@ use Symfony\Component\Validator\Mapping\AutoMappingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader; use Symfony\Component\Validator\Mapping\PropertyMetadata; -use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; use Symfony\Component\Validator\Tests\Fixtures\PropertyInfoLoaderEntity; use Symfony\Component\Validator\Tests\Fixtures\PropertyInfoLoaderNoAutoMappingEntity; use Symfony\Component\Validator\Validation; diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php index 53c77ec338..f08cfd7c98 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -24,6 +24,8 @@ use Symfony\Component\Validator\Constraints\Traverse; use Symfony\Component\Validator\Exception\MappingException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; @@ -32,7 +34,7 @@ class XmlFileLoaderTest extends TestCase public function testLoadClassMetadataReturnsTrueIfSuccessful() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $this->assertTrue($loader->loadClassMetadata($metadata)); } @@ -48,11 +50,11 @@ class XmlFileLoaderTest extends TestCase public function testLoadClassMetadata() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $expected = new ClassMetadata(Entity::class); $expected->setGroupSequence(['Foo', 'Entity']); $expected->addConstraint(new ConstraintA()); $expected->addConstraint(new ConstraintB()); @@ -83,11 +85,11 @@ class XmlFileLoaderTest extends TestCase public function testLoadClassMetadataWithNonStrings() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping-non-strings.xml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $expected = new ClassMetadata(Entity::class); $expected->addPropertyConstraint('firstName', new Regex(['pattern' => '/^1/', 'match' => false])); $properties = $metadata->getPropertyMetadata('firstName'); @@ -99,11 +101,11 @@ class XmlFileLoaderTest extends TestCase public function testLoadGroupSequenceProvider() { $loader = new XmlFileLoader(__DIR__.'/constraint-mapping.xml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); + $metadata = new ClassMetadata(GroupSequenceProviderEntity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); + $expected = new ClassMetadata(GroupSequenceProviderEntity::class); $expected->setGroupSequenceProvider(true); $this->assertEquals($expected, $metadata); @@ -112,7 +114,7 @@ class XmlFileLoaderTest extends TestCase public function testThrowExceptionIfDocTypeIsSet() { $loader = new XmlFileLoader(__DIR__.'/withdoctype.xml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $this->expectException('\Symfony\Component\Validator\Exception\MappingException'); $loader->loadClassMetadata($metadata); @@ -124,7 +126,7 @@ class XmlFileLoaderTest extends TestCase public function testDoNotModifyStateIfExceptionIsThrown() { $loader = new XmlFileLoader(__DIR__.'/withdoctype.xml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); try { $loader->loadClassMetadata($metadata); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php index 57033884d7..c7656503ca 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -21,6 +21,8 @@ use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; @@ -29,7 +31,7 @@ class YamlFileLoaderTest extends TestCase public function testLoadClassMetadataReturnsFalseIfEmpty() { $loader = new YamlFileLoader(__DIR__.'/empty-mapping.yml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $this->assertFalse($loader->loadClassMetadata($metadata)); @@ -45,7 +47,7 @@ class YamlFileLoaderTest extends TestCase { $this->expectException('InvalidArgumentException'); $loader = new YamlFileLoader(__DIR__.'/'.$path); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $loader->loadClassMetadata($metadata); } @@ -64,7 +66,7 @@ class YamlFileLoaderTest extends TestCase public function testDoNotModifyStateIfExceptionIsThrown() { $loader = new YamlFileLoader(__DIR__.'/nonvalid-mapping.yml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); try { $loader->loadClassMetadata($metadata); } catch (\InvalidArgumentException $e) { @@ -77,7 +79,7 @@ class YamlFileLoaderTest extends TestCase public function testLoadClassMetadataReturnsTrueIfSuccessful() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $this->assertTrue($loader->loadClassMetadata($metadata)); } @@ -93,11 +95,11 @@ class YamlFileLoaderTest extends TestCase public function testLoadClassMetadata() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $expected = new ClassMetadata(Entity::class); $expected->setGroupSequence(['Foo', 'Entity']); $expected->addConstraint(new ConstraintA()); $expected->addConstraint(new ConstraintB()); @@ -127,11 +129,11 @@ class YamlFileLoaderTest extends TestCase public function testLoadClassMetadataWithConstants() { $loader = new YamlFileLoader(__DIR__.'/mapping-with-constants.yml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $metadata = new ClassMetadata(Entity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $expected = new ClassMetadata(Entity::class); $expected->addPropertyConstraint('firstName', new Range(['max' => \PHP_INT_MAX])); $this->assertEquals($expected, $metadata); @@ -140,11 +142,11 @@ class YamlFileLoaderTest extends TestCase public function testLoadGroupSequenceProvider() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); - $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); + $metadata = new ClassMetadata(GroupSequenceProviderEntity::class); $loader->loadClassMetadata($metadata); - $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'); + $expected = new ClassMetadata(GroupSequenceProviderEntity::class); $expected->setGroupSequenceProvider(true); $this->assertEquals($expected, $metadata); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/bad-format.yml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/bad-format.yml index d2b4ad2654..8709d23271 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/bad-format.yml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/bad-format.yml @@ -1,7 +1,7 @@ namespaces: custom: Symfony\Component\Validator\Tests\Fixtures\ -Symfony\Component\Validator\Tests\Fixtures\Entity: +Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity: constraints: # Custom constraint - Symfony\Component\Validator\Tests\Fixtures\ConstraintA: ~ diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml index 83945a60d4..02fbeb4311 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping-non-strings.xml @@ -6,7 +6,7 @@ Symfony\Component\Validator\Tests\Fixtures\ - + diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml index 5a7e9d46ee..114d7fc34e 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.xml @@ -6,7 +6,7 @@ Symfony\Component\Validator\Tests\Fixtures\ - + Foo @@ -115,7 +115,7 @@ - + diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml index c39168c96c..5a62b38334 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/constraint-mapping.yml @@ -1,7 +1,7 @@ namespaces: custom: Symfony\Component\Validator\Tests\Fixtures\ -Symfony\Component\Validator\Tests\Fixtures\Entity: +Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity: group_sequence: - Foo - Entity @@ -58,5 +58,5 @@ Symfony\Component\Validator\Tests\Fixtures\Entity: permissions: - "IsTrue": ~ -Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity: +Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity: group_sequence_provider: true diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml index 32ddcc5b5e..afdda04785 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml @@ -1,7 +1,7 @@ namespaces: custom: Symfony\Component\Validator\Tests\Fixtures\ -Symfony\Component\Validator\Tests\Fixtures\Entity: +Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity: properties: firstName: - Range: diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml index 08d614469e..ae7037c562 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/withdoctype.xml @@ -3,5 +3,5 @@ - + diff --git a/src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php index 55e030a2dc..a82ebae9e7 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/MemberMetadataTest.php @@ -18,6 +18,7 @@ use Symfony\Component\Validator\Constraints\Required; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Mapping\MemberMetadata; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; use Symfony\Component\Validator\Tests\Fixtures\ClassConstraint; use Symfony\Component\Validator\Tests\Fixtures\ConstraintA; use Symfony\Component\Validator\Tests\Fixtures\ConstraintB; @@ -30,7 +31,7 @@ class MemberMetadataTest extends TestCase protected function setUp(): void { $this->metadata = new TestMemberMetadata( - 'Symfony\Component\Validator\Tests\Fixtures\Entity', + Entity::class, 'getLastName', 'lastName' ); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php index 8868ec64aa..f00e0c63ac 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php @@ -13,16 +13,17 @@ namespace Symfony\Component\Validator\Tests\Mapping; use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Mapping\PropertyMetadata; -use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\EntityParent; use Symfony\Component\Validator\Tests\Fixtures\Entity_74; use Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy; class PropertyMetadataTest extends TestCase { - const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; + const CLASSNAME = Entity::class; const CLASSNAME_74 = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74'; const CLASSNAME_74_PROXY = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy'; - const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; + const PARENTCLASS = EntityParent::class; public function testInvalidPropertyName() { diff --git a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php index 5d82a2ba34..b836a11e81 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php @@ -24,9 +24,9 @@ use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; use Symfony\Component\Validator\Tests\Fixtures\CascadedChild; use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity; -use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Tests\Fixtures\FailingConstraint; use Symfony\Component\Validator\Tests\Fixtures\Reference; use Symfony\Component\Validator\Validator\ValidatorInterface; diff --git a/src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php index e9bad07096..57a374915c 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/AbstractValidatorTest.php @@ -18,9 +18,9 @@ use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\FakeMetadataFactory; -use Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity; use Symfony\Component\Validator\Tests\Fixtures\Reference; /** @@ -28,7 +28,7 @@ use Symfony\Component\Validator\Tests\Fixtures\Reference; */ abstract class AbstractValidatorTest extends TestCase { - const ENTITY_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; + const ENTITY_CLASS = Entity::class; const REFERENCE_CLASS = 'Symfony\Component\Validator\Tests\Fixtures\Reference'; diff --git a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php index ec2d8f1eec..c7e26680f3 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php @@ -30,10 +30,10 @@ use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\Entity; +use Symfony\Component\Validator\Tests\Fixtures\Annotation\EntityParent; use Symfony\Component\Validator\Tests\Fixtures\CascadedChild; use Symfony\Component\Validator\Tests\Fixtures\CascadingEntity; -use Symfony\Component\Validator\Tests\Fixtures\Entity; -use Symfony\Component\Validator\Tests\Fixtures\EntityParent; use Symfony\Component\Validator\Tests\Fixtures\EntityWithGroupedConstraintOnMethods; use Symfony\Component\Validator\Validator\RecursiveValidator; use Symfony\Component\Validator\Validator\ValidatorInterface; diff --git a/src/Symfony/Component/VarDumper/Tests/Fixtures/MyAttribute.php b/src/Symfony/Component/VarDumper/Tests/Fixtures/MyAttribute.php index a466fd6b8a..e84ca0fd45 100644 --- a/src/Symfony/Component/VarDumper/Tests/Fixtures/MyAttribute.php +++ b/src/Symfony/Component/VarDumper/Tests/Fixtures/MyAttribute.php @@ -11,9 +11,7 @@ namespace Symfony\Component\VarDumper\Tests\Fixtures; -use Attribute; - -#[Attribute] +#[\Attribute] final class MyAttribute { public function __construct( diff --git a/src/Symfony/Component/VarDumper/Tests/Fixtures/RepeatableAttribute.php b/src/Symfony/Component/VarDumper/Tests/Fixtures/RepeatableAttribute.php index bb3b5995af..49aac9fc50 100644 --- a/src/Symfony/Component/VarDumper/Tests/Fixtures/RepeatableAttribute.php +++ b/src/Symfony/Component/VarDumper/Tests/Fixtures/RepeatableAttribute.php @@ -11,9 +11,7 @@ namespace Symfony\Component\VarDumper\Tests\Fixtures; -use Attribute; - -#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS_CONST | Attribute::TARGET_PROPERTY)] +#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS_CONST | \Attribute::TARGET_PROPERTY)] final class RepeatableAttribute { private string $string; diff --git a/src/Symfony/Contracts/Service/Attribute/Required.php b/src/Symfony/Contracts/Service/Attribute/Required.php index 8ba6183f6e..9df851189a 100644 --- a/src/Symfony/Contracts/Service/Attribute/Required.php +++ b/src/Symfony/Contracts/Service/Attribute/Required.php @@ -11,8 +11,6 @@ namespace Symfony\Contracts\Service\Attribute; -use Attribute; - /** * A required dependency. * @@ -21,7 +19,7 @@ use Attribute; * * @author Alexander M. Turek */ -#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_PROPERTY)] +#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] final class Required { }