diff --git a/AbstractType.php b/AbstractType.php index 8fffa379d8..74548bc602 100644 --- a/AbstractType.php +++ b/AbstractType.php @@ -20,46 +20,28 @@ */ abstract class AbstractType implements FormTypeInterface { - /** - * @return string|null - */ - public function getParent() + public function getParent(): ?string { return FormType::class; } - /** - * @return void - */ - public function configureOptions(OptionsResolver $resolver) + public function configureOptions(OptionsResolver $resolver): void { } - /** - * @return void - */ - public function buildForm(FormBuilderInterface $builder, array $options) + public function buildForm(FormBuilderInterface $builder, array $options): void { } - /** - * @return void - */ - public function buildView(FormView $view, FormInterface $form, array $options) + public function buildView(FormView $view, FormInterface $form, array $options): void { } - /** - * @return void - */ - public function finishView(FormView $view, FormInterface $form, array $options) + public function finishView(FormView $view, FormInterface $form, array $options): void { } - /** - * @return string - */ - public function getBlockPrefix() + public function getBlockPrefix(): string { return StringUtil::fqcnToBlockPrefix(static::class) ?: ''; } diff --git a/CHANGELOG.md b/CHANGELOG.md index 00d3b2fc40..92a6244b33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ CHANGELOG ========= +8.0 +--- + + * Change default value of `default_protocol` option in `UrlType` from `'http'` to `null` + * Remove the `VersionAwareTest` trait, use feature detection instead + * Remove deprecated `ResizeFormListener::preSetData()` method, use `postSetData()` instead + * Remove `validation.xml` in `Resources/config`, replaced by attributes on the `Form` class + +7.4 +--- + + * Add `input=date_point` to `DateTimeType`, `DateType` and `TimeType` + * Add support for guessing form type of enum properties + 7.3 --- @@ -15,6 +29,7 @@ CHANGELOG * Add `LazyChoiceLoader` and `choice_lazy` option in `ChoiceType` for loading and rendering choices on demand * Use `form.post_set_data` instead of `form.pre_set_data` in `ResizeFormListener` * Change the priority of `DataCollectorListener` from 255 to -255 + * Make `ResizeFormListener::postSetData()` method `final` 7.1 --- diff --git a/Command/DebugCommand.php b/Command/DebugCommand.php index 91db6f1a91..20146f02c0 100644 --- a/Command/DebugCommand.php +++ b/Command/DebugCommand.php @@ -56,33 +56,33 @@ protected function configure(): void new InputOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions())), 'txt'), ]) ->setHelp(<<<'EOF' -The %command.name% command displays information about form types. + The %command.name% command displays information about form types. - php %command.full_name% + php %command.full_name% -The command lists all built-in types, services types, type extensions and -guessers currently available. + The command lists all built-in types, services types, type extensions and + guessers currently available. - php %command.full_name% Symfony\Component\Form\Extension\Core\Type\ChoiceType - php %command.full_name% ChoiceType + php %command.full_name% Symfony\Component\Form\Extension\Core\Type\ChoiceType + php %command.full_name% ChoiceType -The command lists all defined options that contains the given form type, -as well as their parents and type extensions. + The command lists all defined options that contains the given form type, + as well as their parents and type extensions. - php %command.full_name% ChoiceType choice_value + php %command.full_name% ChoiceType choice_value -Use the --show-deprecated option to display form types with -deprecated options or the deprecated options of the given form type: + Use the --show-deprecated option to display form types with + deprecated options or the deprecated options of the given form type: - php %command.full_name% --show-deprecated - php %command.full_name% ChoiceType --show-deprecated + php %command.full_name% --show-deprecated + php %command.full_name% ChoiceType --show-deprecated -The command displays the definition of the given option name. + The command displays the definition of the given option name. - php %command.full_name% --format=json + php %command.full_name% --format=json -The command lists everything in a machine readable json format. -EOF + The command lists everything in a machine readable json format. + EOF ) ; } diff --git a/DependencyInjection/FormPass.php b/DependencyInjection/FormPass.php index bec1782d40..812a8b98f3 100644 --- a/DependencyInjection/FormPass.php +++ b/DependencyInjection/FormPass.php @@ -54,7 +54,7 @@ private function processFormTypes(ContainerBuilder $container): Reference // Add form type service to the service locator $serviceDefinition = $container->getDefinition($serviceId); $servicesMap[$formType = $serviceDefinition->getClass()] = new Reference($serviceId); - $namespaces[substr($formType, 0, strrpos($formType, '\\'))] = true; + $namespaces[substr($formType, 0, strrpos($formType, '\\') ?: \strlen($formType))] = true; if (isset($tag[0]['csrf_token_id'])) { $csrfTokenIds[$formType] = $tag[0]['csrf_token_id']; diff --git a/EnumFormTypeGuesser.php b/EnumFormTypeGuesser.php new file mode 100644 index 0000000000..79c3b8abb2 --- /dev/null +++ b/EnumFormTypeGuesser.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +use Symfony\Component\Form\Extension\Core\Type\EnumType; +use Symfony\Component\Form\Guess\Guess; +use Symfony\Component\Form\Guess\TypeGuess; +use Symfony\Component\Form\Guess\ValueGuess; + +final class EnumFormTypeGuesser implements FormTypeGuesserInterface +{ + /** + * @var array> + */ + private array $cache = []; + + public function guessType(string $class, string $property): ?TypeGuess + { + if (!($enum = $this->getPropertyType($class, $property))) { + return null; + } + + return new TypeGuess(EnumType::class, ['class' => ltrim($enum, '?')], Guess::HIGH_CONFIDENCE); + } + + public function guessRequired(string $class, string $property): ?ValueGuess + { + if (!($enum = $this->getPropertyType($class, $property))) { + return null; + } + + return new ValueGuess('?' !== $enum[0], Guess::HIGH_CONFIDENCE); + } + + public function guessMaxLength(string $class, string $property): ?ValueGuess + { + return null; + } + + public function guessPattern(string $class, string $property): ?ValueGuess + { + return null; + } + + private function getPropertyType(string $class, string $property): string|false + { + if (isset($this->cache[$class][$property])) { + return $this->cache[$class][$property]; + } + + try { + $propertyReflection = new \ReflectionProperty($class, $property); + } catch (\ReflectionException) { + return $this->cache[$class][$property] = false; + } + + $type = $propertyReflection->getType(); + if (!$type instanceof \ReflectionNamedType || !enum_exists($type->getName())) { + $enum = false; + } else { + $enum = $type->getName(); + if ($type->allowsNull()) { + $enum = '?'.$enum; + } + } + + return $this->cache[$class][$property] = $enum; + } +} diff --git a/Extension/Core/DataAccessor/PropertyPathAccessor.php b/Extension/Core/DataAccessor/PropertyPathAccessor.php index 33d01fd4f5..3427a9753d 100644 --- a/Extension/Core/DataAccessor/PropertyPathAccessor.php +++ b/Extension/Core/DataAccessor/PropertyPathAccessor.php @@ -100,10 +100,7 @@ private function getPropertyValue(object|array $data, PropertyPathInterface $pro return null; } - if (!$e instanceof UninitializedPropertyException - // For versions without UninitializedPropertyException check the exception message - && (class_exists(UninitializedPropertyException::class) || !str_contains($e->getMessage(), 'You should initialize it')) - ) { + if (!$e instanceof UninitializedPropertyException) { throw $e; } diff --git a/Extension/Core/DataTransformer/DatePointToDateTimeTransformer.php b/Extension/Core/DataTransformer/DatePointToDateTimeTransformer.php new file mode 100644 index 0000000000..dc1f750682 --- /dev/null +++ b/Extension/Core/DataTransformer/DatePointToDateTimeTransformer.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\DataTransformer; + +use Symfony\Component\Clock\DatePoint; +use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\TransformationFailedException; + +/** + * Transforms between a DatePoint object and a DateTime object. + * + * @implements DataTransformerInterface + */ +final class DatePointToDateTimeTransformer implements DataTransformerInterface +{ + /** + * Transforms a DatePoint into a DateTime object. + * + * @param DatePoint|null $value A DatePoint object + * + * @throws TransformationFailedException If the given value is not a DatePoint + */ + public function transform(mixed $value): ?\DateTime + { + if (null === $value) { + return null; + } + + if (!$value instanceof DatePoint) { + throw new TransformationFailedException(\sprintf('Expected a "%s".', DatePoint::class)); + } + + return \DateTime::createFromImmutable($value); + } + + /** + * Transforms a DateTime object into a DatePoint object. + * + * @param \DateTime|null $value A DateTime object + * + * @throws TransformationFailedException If the given value is not a \DateTime + */ + public function reverseTransform(mixed $value): ?DatePoint + { + if (null === $value) { + return null; + } + + if (!$value instanceof \DateTime) { + throw new TransformationFailedException('Expected a \DateTime.'); + } + + return DatePoint::createFromMutable($value); + } +} diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index a7da65bdb6..c8fd3eb036 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -28,9 +28,6 @@ class ResizeFormListener implements EventSubscriberInterface protected array $prototypeOptions; private \Closure|bool $deleteEmpty; - // BC, to be removed in 8.0 - private bool $overridden = true; - private bool $usePreSetData = false; public function __construct( private string $type, @@ -48,7 +45,6 @@ public function __construct( public static function getSubscribedEvents(): array { return [ - FormEvents::PRE_SET_DATA => 'preSetData', // deprecated FormEvents::POST_SET_DATA => ['postSetData', 255], // as early as possible FormEvents::PRE_SUBMIT => 'preSubmit', // (MergeCollectionListener, MergeDoctrineCollectionListener) @@ -56,49 +52,8 @@ public static function getSubscribedEvents(): array ]; } - /** - * @deprecated Since Symfony 7.2, use {@see postSetData()} instead. - */ - public function preSetData(FormEvent $event): void + final public function postSetData(PostSetDataEvent $event): void { - if (__CLASS__ === static::class - || __CLASS__ === (new \ReflectionClass($this))->getMethod('preSetData')->getDeclaringClass()->name - ) { - // not a child class, or child class does not overload PRE_SET_DATA - return; - } - - trigger_deprecation('symfony/form', '7.2', 'Calling "%s()" is deprecated, use "%s::postSetData()" instead.', __METHOD__, __CLASS__); - // parent::preSetData() has been called - $this->overridden = false; - try { - $this->postSetData($event); - } finally { - $this->usePreSetData = true; - } - } - - /** - * Remove FormEvent type hint in 8.0. - * - * @final since Symfony 7.2 - */ - public function postSetData(FormEvent|PostSetDataEvent $event): void - { - if (__CLASS__ !== static::class) { - if ($this->overridden) { - trigger_deprecation('symfony/form', '7.2', 'Calling "%s::preSetData()" is deprecated, use "%s::postSetData()" instead.', static::class, __CLASS__); - // parent::preSetData() has not been called, noop - - return; - } - - if ($this->usePreSetData) { - // nothing else to do - return; - } - } - $form = $event->getForm(); $data = $event->getData() ?? []; diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index fc083ee40d..5c5503a83b 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -100,8 +100,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void if ($options['expanded'] || $options['multiple']) { // Make sure that scalar, submitted values are converted to arrays // which can be submitted to the checkboxes/radio buttons - $builder->addEventListener(FormEvents::PRE_SUBMIT, static function (FormEvent $event) use ($choiceList, $options, &$unknownValues) { - /** @var PreSubmitEvent $event */ + $builder->addEventListener(FormEvents::PRE_SUBMIT, static function (PreSubmitEvent $event) use ($choiceList, $options, &$unknownValues) { $form = $event->getForm(); $data = $event->getData(); diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index cf4c2b7416..8ecaa63c07 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -11,10 +11,12 @@ namespace Symfony\Component\Form\Extension\Core\Type; +use Symfony\Component\Clock\DatePoint; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\DataTransformer\ArrayToPartsTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DataTransformerChain; +use Symfony\Component\Form\Extension\Core\DataTransformer\DatePointToDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToHtml5LocalDateTimeTransformer; @@ -178,7 +180,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ; } - if ('datetime_immutable' === $options['input']) { + if ('date_point' === $options['input']) { + if (!class_exists(DatePoint::class)) { + throw new LogicException(\sprintf('The "symfony/clock" component is required to use "%s" with option "input=date_point". Try running "composer require symfony/clock".', self::class)); + } + $builder->addModelTransformer(new DatePointToDateTimeTransformer()); + } elseif ('datetime_immutable' === $options['input']) { $builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer()); } elseif ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( @@ -194,7 +201,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void )); } - if (\in_array($options['input'], ['datetime', 'datetime_immutable'], true) && null !== $options['model_timezone']) { + if (\in_array($options['input'], ['datetime', 'datetime_immutable', 'date_point'], true) && null !== $options['model_timezone']) { $builder->addEventListener(FormEvents::POST_SET_DATA, static function (FormEvent $event) use ($options): void { $date = $event->getData(); @@ -283,6 +290,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedValues('input', [ 'datetime', 'datetime_immutable', + 'date_point', 'string', 'timestamp', 'array', diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 36b430e144..5c8dfaa3c2 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -11,8 +11,10 @@ namespace Symfony\Component\Form\Extension\Core\Type; +use Symfony\Component\Clock\DatePoint; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Exception\LogicException; +use Symfony\Component\Form\Extension\Core\DataTransformer\DatePointToDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; @@ -156,7 +158,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void ; } - if ('datetime_immutable' === $options['input']) { + if ('date_point' === $options['input']) { + if (!class_exists(DatePoint::class)) { + throw new LogicException(\sprintf('The "symfony/clock" component is required to use "%s" with option "input=date_point". Try running "composer require symfony/clock".', self::class)); + } + $builder->addModelTransformer(new DatePointToDateTimeTransformer()); + } elseif ('datetime_immutable' === $options['input']) { $builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer()); } elseif ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( @@ -172,7 +179,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void )); } - if (\in_array($options['input'], ['datetime', 'datetime_immutable'], true) && null !== $options['model_timezone']) { + if (\in_array($options['input'], ['datetime', 'datetime_immutable', 'date_point'], true) && null !== $options['model_timezone']) { $builder->addEventListener(FormEvents::POST_SET_DATA, static function (FormEvent $event) use ($options): void { $date = $event->getData(); @@ -298,6 +305,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedValues('input', [ 'datetime', 'datetime_immutable', + 'date_point', 'string', 'timestamp', 'array', diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 92cf42d963..1622301aed 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -11,9 +11,11 @@ namespace Symfony\Component\Form\Extension\Core\Type; +use Symfony\Component\Clock\DatePoint; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Exception\LogicException; +use Symfony\Component\Form\Extension\Core\DataTransformer\DatePointToDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; @@ -190,7 +192,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'], $options['reference_date'])); } - if ('datetime_immutable' === $options['input']) { + if ('date_point' === $options['input']) { + if (!class_exists(DatePoint::class)) { + throw new LogicException(\sprintf('The "symfony/clock" component is required to use "%s" with option "input=date_point". Try running "composer require symfony/clock".', self::class)); + } + $builder->addModelTransformer(new DatePointToDateTimeTransformer()); + } elseif ('datetime_immutable' === $options['input']) { $builder->addModelTransformer(new DateTimeImmutableToDateTimeTransformer()); } elseif ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( @@ -206,7 +213,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void )); } - if (\in_array($options['input'], ['datetime', 'datetime_immutable'], true) && null !== $options['model_timezone']) { + if (\in_array($options['input'], ['datetime', 'datetime_immutable', 'date_point'], true) && null !== $options['model_timezone']) { $builder->addEventListener(FormEvents::POST_SET_DATA, static function (FormEvent $event) use ($options): void { $date = $event->getData(); @@ -354,6 +361,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedValues('input', [ 'datetime', 'datetime_immutable', + 'date_point', 'string', 'timestamp', 'array', diff --git a/Extension/Core/Type/UrlType.php b/Extension/Core/Type/UrlType.php index fd6025729a..a70b4004c4 100644 --- a/Extension/Core/Type/UrlType.php +++ b/Extension/Core/Type/UrlType.php @@ -16,7 +16,6 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; -use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class UrlType extends AbstractType @@ -39,11 +38,7 @@ public function buildView(FormView $view, FormInterface $form, array $options): public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ - 'default_protocol' => static function (Options $options) { - trigger_deprecation('symfony/form', '7.1', 'Not configuring the "default_protocol" option when using the UrlType is deprecated. It will default to "null" in 8.0.'); - - return 'http'; - }, + 'default_protocol' => null, 'invalid_message' => 'Please enter a valid URL.', ]); diff --git a/Extension/DataCollector/FormDataCollector.php b/Extension/DataCollector/FormDataCollector.php index e6cae863e8..7ed4e06db8 100644 --- a/Extension/DataCollector/FormDataCollector.php +++ b/Extension/DataCollector/FormDataCollector.php @@ -200,7 +200,7 @@ public function getData(): array|Data /** * @internal */ - public function __sleep(): array + public function __serialize(): array { foreach ($this->data['forms_by_hash'] as &$form) { if (isset($form['type_class']) && !$form['type_class'] instanceof ClassStub) { @@ -208,9 +208,7 @@ public function __sleep(): array } } - $this->data = $this->cloneVar($this->data); - - return parent::__sleep(); + return ['data' => $this->data = $this->cloneVar($this->data)]; } protected function getCasters(): array diff --git a/Extension/DataCollector/FormDataExtractor.php b/Extension/DataCollector/FormDataExtractor.php index f56fe911fa..761dcc9091 100644 --- a/Extension/DataCollector/FormDataExtractor.php +++ b/Extension/DataCollector/FormDataExtractor.php @@ -98,7 +98,7 @@ public function extractSubmittedData(FormInterface $form): array while (null !== $cause) { if ($cause instanceof ConstraintViolationInterface) { $errorData['trace'][] = $cause; - $cause = method_exists($cause, 'getCause') ? $cause->getCause() : null; + $cause = $cause->getCause(); continue; } diff --git a/Extension/Validator/Constraints/Form.php b/Extension/Validator/Constraints/Form.php index 8be25c0b8b..6c45090b08 100644 --- a/Extension/Validator/Constraints/Form.php +++ b/Extension/Validator/Constraints/Form.php @@ -11,11 +11,13 @@ namespace Symfony\Component\Form\Extension\Validator\Constraints; +use Symfony\Component\Validator\Attribute\HasNamedArguments; use Symfony\Component\Validator\Constraint; /** * @author Bernhard Schussek */ +#[\Attribute(\Attribute::TARGET_CLASS)] class Form extends Constraint { public const NOT_SYNCHRONIZED_ERROR = '1dafa156-89e1-4736-b832-419c2e501fca'; @@ -26,6 +28,12 @@ class Form extends Constraint self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR', ]; + #[HasNamedArguments] + public function __construct(mixed $options = null, ?array $groups = null, mixed $payload = null) + { + parent::__construct($options, $groups, $payload); + } + public function getTargets(): string|array { return self::CLASS_CONSTRAINT; diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 08dc6e2d58..cb153d88a9 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -207,7 +207,7 @@ public function guessMaxLengthForConstraint(Constraint $constraint): ?ValueGuess break; case Type::class: - if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'])) { + if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'], true)) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; @@ -249,7 +249,7 @@ public function guessPatternForConstraint(Constraint $constraint): ?ValueGuess break; case Type::class: - if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'])) { + if (\in_array($constraint->type, ['double', 'float', 'numeric', 'real'], true)) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index c6ef92bf3a..981865b2ba 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -228,6 +228,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ $foundAtIndex = null; // Construct mapping rules for the given form + /** @var MappingRule[] $rules */ $rules = []; foreach ($form->getConfig()->getOption('error_mapping') as $propertyPath => $targetPath) { @@ -237,6 +238,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ } } + /** @var FormInterface[] $children */ $children = iterator_to_array(new \RecursiveIteratorIterator(new InheritDataAwareIterator($form)), false); while ($it->valid()) { @@ -248,8 +250,6 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ // Test mapping rules as long as we have any foreach ($rules as $key => $rule) { - /** @var MappingRule $rule */ - // Mapping rule matches completely, terminate. if (null !== ($form = $rule->match($chunk))) { return $form; @@ -261,7 +261,6 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ } } - /** @var FormInterface $child */ foreach ($children as $i => $child) { $childPath = (string) $child->getPropertyPath(); if ($childPath === $chunk) { @@ -312,7 +311,6 @@ private function reconstructPath(ViolationPath $violationPath, FormInterface $or // Cut the piece out of the property path and proceed $propertyPathBuilder->remove($i); } else { - /** @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ $propertyPath = $scope->getPropertyPath(); if (null === $propertyPath) { diff --git a/Form.php b/Form.php index 72c60ee41a..98ebfe19ec 100644 --- a/Form.php +++ b/Form.php @@ -22,11 +22,13 @@ use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\Extension\Validator\Constraints\Form as AssertForm; use Symfony\Component\Form\Util\FormUtil; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\Form\Util\OrderedHashMap; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; +use Symfony\Component\Validator\Constraints\Traverse; /** * Form represents a form. @@ -68,6 +70,8 @@ * * @implements \IteratorAggregate */ +#[AssertForm] +#[Traverse(false)] class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterface { private ?FormInterface $parent = null; @@ -301,7 +305,7 @@ public function setData(mixed $modelData): static if (null !== $dataClass && !$viewData instanceof $dataClass) { $actualType = get_debug_type($viewData); - throw new LogicException('The form\'s view data is expected to be a "'.$dataClass.'", but it is a "'.$actualType.'". You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms "'.$actualType.'" to an instance of "'.$dataClass.'".'); + throw new LogicException(\sprintf('The form\'s view data is expected to be a "%s", but it is a "%s". You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms "%2$s" to an instance of "%1$s".', $dataClass, $actualType)); } } diff --git a/FormError.php b/FormError.php index 335d9e21d3..29c9764e51 100644 --- a/FormError.php +++ b/FormError.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; +use Symfony\Component\Translation\Translator; /** * Wraps errors in forms. @@ -38,7 +39,7 @@ class FormError * @param int|null $messagePluralization The value for error message pluralization * @param mixed $cause The cause of the error * - * @see \Symfony\Component\Translation\Translator + * @see Translator */ public function __construct( private string $message, diff --git a/FormTypeInterface.php b/FormTypeInterface.php index 2bc9f7711e..6a27b59bba 100644 --- a/FormTypeInterface.php +++ b/FormTypeInterface.php @@ -23,17 +23,13 @@ interface FormTypeInterface * * The parent type and its extensions will configure the form with the * following methods before the current implementation. - * - * @return string|null */ - public function getParent(); + public function getParent(): ?string; /** * Configures the options for this type. - * - * @return void */ - public function configureOptions(OptionsResolver $resolver); + public function configureOptions(OptionsResolver $resolver): void; /** * Builds the form. @@ -43,11 +39,9 @@ public function configureOptions(OptionsResolver $resolver); * * @param array $options * - * @return void - * * @see FormTypeExtensionInterface::buildForm() */ - public function buildForm(FormBuilderInterface $builder, array $options); + public function buildForm(FormBuilderInterface $builder, array $options): void; /** * Builds the form view. @@ -61,11 +55,9 @@ public function buildForm(FormBuilderInterface $builder, array $options); * * @param array $options * - * @return void - * * @see FormTypeExtensionInterface::buildView() */ - public function buildView(FormView $view, FormInterface $form, array $options); + public function buildView(FormView $view, FormInterface $form, array $options): void; /** * Finishes the form view. @@ -80,19 +72,15 @@ public function buildView(FormView $view, FormInterface $form, array $options); * * @param array $options * - * @return void - * * @see FormTypeExtensionInterface::finishView() */ - public function finishView(FormView $view, FormInterface $form, array $options); + public function finishView(FormView $view, FormInterface $form, array $options): void; /** * Returns the prefix of the template block name for this type. * * The block prefix defaults to the underscored short class name with * the "Type" suffix removed (e.g. "UserProfileType" => "user_profile"). - * - * @return string */ - public function getBlockPrefix(); + public function getBlockPrefix(): string; } diff --git a/ResolvedFormType.php b/ResolvedFormType.php index d9553bbbbd..e2c5186466 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -117,7 +117,6 @@ public function finishView(FormView $view, FormInterface $form, array $options): $this->innerType->finishView($view, $form, $options); - /** @var FormTypeExtensionInterface $extension */ foreach ($this->typeExtensions as $extension) { $extension->finishView($view, $form, $options); } diff --git a/Resources/config/validation.xml b/Resources/config/validation.xml deleted file mode 100644 index 918f101f42..0000000000 --- a/Resources/config/validation.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/Test/FormIntegrationTestCase.php b/Test/FormIntegrationTestCase.php index 8756d99689..34530bc4ba 100644 --- a/Test/FormIntegrationTestCase.php +++ b/Test/FormIntegrationTestCase.php @@ -39,7 +39,7 @@ protected function setUp(): void /** * @return FormExtensionInterface[] */ - protected function getExtensions() + protected function getExtensions(): array { return []; } @@ -47,7 +47,7 @@ protected function getExtensions() /** * @return FormTypeExtensionInterface[] */ - protected function getTypeExtensions() + protected function getTypeExtensions(): array { return []; } @@ -55,7 +55,7 @@ protected function getTypeExtensions() /** * @return FormTypeInterface[] */ - protected function getTypes() + protected function getTypes(): array { return []; } @@ -63,7 +63,7 @@ protected function getTypes() /** * @return FormTypeGuesserInterface[] */ - protected function getTypeGuessers() + protected function getTypeGuessers(): array { return []; } diff --git a/Test/TypeTestCase.php b/Test/TypeTestCase.php index 1bbb66d25d..89aee9bffb 100644 --- a/Test/TypeTestCase.php +++ b/Test/TypeTestCase.php @@ -32,7 +32,7 @@ protected function setUp(): void /** * @return FormExtensionInterface[] */ - protected function getExtensions() + protected function getExtensions(): array { $extensions = []; @@ -43,18 +43,12 @@ protected function getExtensions() return $extensions; } - /** - * @return void - */ - public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) + public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual): void { self::assertEquals($expected->format('c'), $actual->format('c')); } - /** - * @return void - */ - public static function assertDateIntervalEquals(\DateInterval $expected, \DateInterval $actual) + public static function assertDateIntervalEquals(\DateInterval $expected, \DateInterval $actual): void { self::assertEquals($expected->format('%RP%yY%mM%dDT%hH%iM%sS'), $actual->format('%RP%yY%mM%dDT%hH%iM%sS')); } diff --git a/Tests/AbstractRequestHandlerTestCase.php b/Tests/AbstractRequestHandlerTestCase.php index f80efffb71..68dfafab16 100644 --- a/Tests/AbstractRequestHandlerTestCase.php +++ b/Tests/AbstractRequestHandlerTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper; @@ -76,9 +77,7 @@ public static function methodProvider(): array ], self::methodExceptGetProvider()); } - /** - * @dataProvider methodProvider - */ + #[DataProvider('methodProvider')] public function testSubmitIfNameInRequest($method) { $form = $this->createForm('param1', $method); @@ -93,9 +92,7 @@ public function testSubmitIfNameInRequest($method) $this->assertSame('DATA', $form->getData()); } - /** - * @dataProvider methodProvider - */ + #[DataProvider('methodProvider')] public function testDoNotSubmitIfWrongRequestMethod($method) { $form = $this->createForm('param1', $method); @@ -111,9 +108,7 @@ public function testDoNotSubmitIfWrongRequestMethod($method) $this->assertFalse($form->isSubmitted()); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->createForm('param1', $method, false); @@ -127,9 +122,7 @@ public function testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($meth $this->assertFalse($form->isSubmitted()); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testDoNotSubmitCompoundFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->createForm('param1', $method, true); @@ -156,9 +149,7 @@ public function testDoNotSubmitIfNameNotInRequestAndGetRequest() $this->assertFalse($form->isSubmitted()); } - /** - * @dataProvider methodProvider - */ + #[DataProvider('methodProvider')] public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method) { $form = $this->createForm('', $method, true); @@ -185,9 +176,7 @@ public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method) $this->assertNull($form->get('param2')->getData()); } - /** - * @dataProvider methodProvider - */ + #[DataProvider('methodProvider')] public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method) { $form = $this->createForm('', $method, true); @@ -203,9 +192,7 @@ public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method) $this->assertFalse($form->isSubmitted()); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testMergeParamsAndFiles($method) { $form = $this->createForm('param1', $method, true); @@ -248,9 +235,7 @@ public function testIntegerChildren() $this->assertSame('bar', $form->get('1')->getData()); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testMergeParamsAndFilesMultiple($method) { $form = $this->createForm('param1', $method, true); @@ -284,9 +269,7 @@ public function testMergeParamsAndFilesMultiple($method) $this->assertSame(['foo', 'bar', 'baz', $file1, $file2], $data); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testParamTakesPrecedenceOverFile($method) { $form = $this->createForm('param1', $method); @@ -346,9 +329,7 @@ public function testMergeZeroIndexedCollection() $this->assertNotNull($itemsForm->get('0')->get('file')); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testSubmitFileIfNoParam($method) { $form = $this->createBuilder('param1', false, ['allow_file_upload' => true]) @@ -368,9 +349,7 @@ public function testSubmitFileIfNoParam($method) $this->assertSame($file, $form->getData()); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testSubmitMultipleFiles($method) { $form = $this->createBuilder('param1', false, ['allow_file_upload' => true]) @@ -392,9 +371,7 @@ public function testSubmitMultipleFiles($method) $this->assertSame($file, $form->getData()); } - /** - * @dataProvider methodExceptGetProvider - */ + #[DataProvider('methodExceptGetProvider')] public function testSubmitFileWithNamelessForm($method) { $form = $this->createForm('', $method, true); @@ -412,9 +389,7 @@ public function testSubmitFileWithNamelessForm($method) $this->assertSame($file, $fileForm->getData()); } - /** - * @dataProvider getPostMaxSizeFixtures - */ + #[DataProvider('getPostMaxSizeFixtures')] public function testAddFormErrorIfPostMaxSizeExceeded(?int $contentLength, string $iniMax, bool $shouldFail, array $errorParams = []) { $this->serverParams->contentLength = $contentLength; @@ -463,9 +438,7 @@ public function testInvalidFilesAreRejected() $this->assertFalse($this->requestHandler->isFileUpload($this->getInvalidFile())); } - /** - * @dataProvider uploadFileErrorCodes - */ + #[DataProvider('uploadFileErrorCodes')] public function testFailedFileUploadIsTurnedIntoFormError($errorCode, $expectedErrorCode) { $this->assertSame($expectedErrorCode, $this->requestHandler->getUploadFileError($this->getFailedUploadedFile($errorCode))); diff --git a/Tests/ButtonBuilderTest.php b/Tests/ButtonBuilderTest.php index 71668dd028..c625b1f25e 100644 --- a/Tests/ButtonBuilderTest.php +++ b/Tests/ButtonBuilderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\ButtonBuilder; use Symfony\Component\Form\Exception\InvalidArgumentException; @@ -31,9 +32,7 @@ public static function getValidNames() ]; } - /** - * @dataProvider getValidNames - */ + #[DataProvider('getValidNames')] public function testValidNames($name) { $this->assertInstanceOf(ButtonBuilder::class, new ButtonBuilder($name)); @@ -51,14 +50,11 @@ public static function getInvalidNames() { return [ [''], - [false], [null], ]; } - /** - * @dataProvider getInvalidNames - */ + #[DataProvider('getInvalidNames')] public function testInvalidNames($name) { $this->expectException(InvalidArgumentException::class); diff --git a/Tests/ButtonTest.php b/Tests/ButtonTest.php index 9431328e2f..e0b276e5fc 100644 --- a/Tests/ButtonTest.php +++ b/Tests/ButtonTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\ButtonBuilder; @@ -37,9 +38,7 @@ public function testSetParentOnSubmittedButton() $button->setParent($this->getFormBuilder()->getForm()); } - /** - * @dataProvider getDisabledStates - */ + #[DataProvider('getDisabledStates')] public function testDisabledIfParentIsDisabled($parentDisabled, $buttonDisabled, $result) { $form = $this->getFormBuilder() diff --git a/Tests/ChoiceList/ChoiceListAssertionTrait.php b/Tests/ChoiceList/ChoiceListAssertionTrait.php new file mode 100644 index 0000000000..f0b03d13e3 --- /dev/null +++ b/Tests/ChoiceList/ChoiceListAssertionTrait.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\Form\Tests\ChoiceList; + +use Symfony\Component\Form\ChoiceList\ArrayChoiceList; +use Symfony\Component\Form\ChoiceList\LazyChoiceList; + +trait ChoiceListAssertionTrait +{ + private function assertEqualsArrayChoiceList(ArrayChoiceList $expected, $actual) + { + $this->assertInstanceOf(ArrayChoiceList::class, $actual); + $this->assertEquals($expected->getChoices(), $actual->getChoices()); + $this->assertEquals($expected->getStructuredValues(), $actual->getStructuredValues()); + $this->assertEquals($expected->getOriginalKeys(), $actual->getOriginalKeys()); + } + + private function assertEqualsLazyChoiceList(LazyChoiceList $expected, $actual) + { + $this->assertInstanceOf(LazyChoiceList::class, $actual); + $this->assertEquals($expected->getChoices(), $actual->getChoices()); + $this->assertEquals($expected->getValues(), $actual->getValues()); + $this->assertEquals($expected->getOriginalKeys(), $actual->getOriginalKeys()); + } +} diff --git a/Tests/ChoiceList/Factory/Cache/ChoiceLoaderTest.php b/Tests/ChoiceList/Factory/Cache/ChoiceLoaderTest.php index 6134160046..0ca1de133f 100644 --- a/Tests/ChoiceList/Factory/Cache/ChoiceLoaderTest.php +++ b/Tests/ChoiceList/Factory/Cache/ChoiceLoaderTest.php @@ -16,10 +16,13 @@ use Symfony\Component\Form\ChoiceList\Factory\Cache\ChoiceLoader; use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\Tests\ChoiceList\ChoiceListAssertionTrait; use Symfony\Component\Form\Tests\Fixtures\ArrayChoiceLoader; class ChoiceLoaderTest extends TestCase { + use ChoiceListAssertionTrait; + public function testSameFormTypeUseCachedLoader() { $choices = ['f' => 'foo', 'b' => 'bar', 'z' => 'baz']; @@ -30,8 +33,8 @@ public function testSameFormTypeUseCachedLoader() $loader1 = new ChoiceLoader($type, $decorated); $loader2 = new ChoiceLoader($type, new ArrayChoiceLoader()); - $this->assertEquals($choiceList, $loader1->loadChoiceList()); - $this->assertEquals($choiceList, $loader2->loadChoiceList()); + $this->assertEqualsArrayChoiceList($choiceList, $loader1->loadChoiceList()); + $this->assertEqualsArrayChoiceList($choiceList, $loader2->loadChoiceList()); $this->assertSame($choices, $loader1->loadChoicesForValues($choices)); $this->assertSame($choices, $loader2->loadChoicesForValues($choices)); diff --git a/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php b/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php index 67e86208c5..fb51e0d572 100644 --- a/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php +++ b/Tests/ChoiceList/Factory/CachingFactoryDecoratorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\ChoiceList\Factory; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\ChoiceList; @@ -21,6 +22,7 @@ use Symfony\Component\Form\ChoiceList\Loader\FilterChoiceLoaderDecorator; use Symfony\Component\Form\ChoiceList\View\ChoiceListView; use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\Tests\ChoiceList\ChoiceListAssertionTrait; use Symfony\Component\Form\Tests\Fixtures\ArrayChoiceLoader; /** @@ -28,6 +30,8 @@ */ class CachingFactoryDecoratorTest extends TestCase { + use ChoiceListAssertionTrait; + private CachingFactoryDecorator $factory; protected function setUp(): void @@ -41,8 +45,8 @@ public function testCreateFromChoicesEmpty() $list2 = $this->factory->createListFromChoices([]); $this->assertSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList([]), $list1); - $this->assertEquals(new ArrayChoiceList([]), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList([]), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList([]), $list2); } public function testCreateFromChoicesComparesTraversableChoicesAsArray() @@ -55,8 +59,8 @@ public function testCreateFromChoicesComparesTraversableChoicesAsArray() $list2 = $this->factory->createListFromChoices($choices2); $this->assertSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList(['A' => 'a']), $list1); - $this->assertEquals(new ArrayChoiceList(['A' => 'a']), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList(['A' => 'a']), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList(['A' => 'a']), $list2); } public function testCreateFromChoicesGroupedChoices() @@ -67,34 +71,30 @@ public function testCreateFromChoicesGroupedChoices() $list2 = $this->factory->createListFromChoices($choices2); $this->assertNotSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList(['key' => ['A' => 'a']]), $list1); - $this->assertEquals(new ArrayChoiceList(['A' => 'a']), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList(['key' => ['A' => 'a']]), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList(['A' => 'a']), $list2); } - /** - * @dataProvider provideSameChoices - */ + #[DataProvider('provideSameChoices')] public function testCreateFromChoicesSameChoices($choice1, $choice2) { $list1 = $this->factory->createListFromChoices([$choice1]); $list2 = $this->factory->createListFromChoices([$choice2]); $this->assertSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList([$choice1]), $list1); - $this->assertEquals(new ArrayChoiceList([$choice2]), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList([$choice1]), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList([$choice2]), $list2); } - /** - * @dataProvider provideDistinguishedChoices - */ + #[DataProvider('provideDistinguishedChoices')] public function testCreateFromChoicesDifferentChoices($choice1, $choice2) { $list1 = $this->factory->createListFromChoices([$choice1]); $list2 = $this->factory->createListFromChoices([$choice2]); $this->assertNotSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList([$choice1]), $list1); - $this->assertEquals(new ArrayChoiceList([$choice2]), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList([$choice1]), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList([$choice2]), $list2); } public function testCreateFromChoicesSameValueClosure() @@ -106,8 +106,8 @@ public function testCreateFromChoicesSameValueClosure() $list2 = $this->factory->createListFromChoices($choices, $closure); $this->assertNotSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList($choices, $closure), $list1); - $this->assertEquals(new ArrayChoiceList($choices, $closure), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList($choices, $closure), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList($choices, $closure), $list2); } public function testCreateFromChoicesSameValueClosureUseCache() @@ -120,8 +120,8 @@ public function testCreateFromChoicesSameValueClosureUseCache() $list2 = $this->factory->createListFromChoices($choices, ChoiceList::value($formType, function () {})); $this->assertSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList($choices, $valueCallback), $list1); - $this->assertEquals(new ArrayChoiceList($choices, function () {}), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList($choices, $valueCallback), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList($choices, function () {}), $list2); } public function testCreateFromChoicesDifferentValueClosure() @@ -133,8 +133,8 @@ public function testCreateFromChoicesDifferentValueClosure() $list2 = $this->factory->createListFromChoices($choices, $closure2); $this->assertNotSame($list1, $list2); - $this->assertEquals(new ArrayChoiceList($choices, $closure1), $list1); - $this->assertEquals(new ArrayChoiceList($choices, $closure2), $list2); + self::assertEqualsArrayChoiceList(new ArrayChoiceList($choices, $closure1), $list1); + self::assertEqualsArrayChoiceList(new ArrayChoiceList($choices, $closure2), $list2); } public function testCreateFromChoicesSameFilterClosure() @@ -146,8 +146,8 @@ public function testCreateFromChoicesSameFilterClosure() $lazyChoiceList = new LazyChoiceList(new FilterChoiceLoaderDecorator(new CallbackChoiceLoader(static fn () => $choices), $filter), null); $this->assertNotSame($list1, $list2); - $this->assertEquals($lazyChoiceList, $list1); - $this->assertEquals($lazyChoiceList, $list2); + self::assertEqualsLazyChoiceList($lazyChoiceList, $list1); + self::assertEqualsLazyChoiceList($lazyChoiceList, $list2); } public function testCreateFromChoicesSameFilterClosureUseCache() @@ -160,8 +160,8 @@ public function testCreateFromChoicesSameFilterClosureUseCache() $lazyChoiceList = new LazyChoiceList(new FilterChoiceLoaderDecorator(new CallbackChoiceLoader(static fn () => $choices), function () {}), null); $this->assertSame($list1, $list2); - $this->assertEquals($lazyChoiceList, $list1); - $this->assertEquals($lazyChoiceList, $list2); + self::assertEqualsLazyChoiceList($lazyChoiceList, $list1); + self::assertEqualsLazyChoiceList($lazyChoiceList, $list2); } public function testCreateFromChoicesDifferentFilterClosure() @@ -174,8 +174,8 @@ public function testCreateFromChoicesDifferentFilterClosure() $lazyChoiceList = new LazyChoiceList(new FilterChoiceLoaderDecorator(new CallbackChoiceLoader(static fn () => $choices), function () {}), null); $this->assertNotSame($list1, $list2); - $this->assertEquals($lazyChoiceList, $list1); - $this->assertEquals($lazyChoiceList, $list2); + self::assertEqualsLazyChoiceList($lazyChoiceList, $list1); + self::assertEqualsLazyChoiceList($lazyChoiceList, $list2); } public function testCreateFromLoaderSameLoader() @@ -185,8 +185,8 @@ public function testCreateFromLoaderSameLoader() $list2 = $this->factory->createListFromLoader($loader); $this->assertNotSame($list1, $list2); - $this->assertEquals(new LazyChoiceList($loader), $list1); - $this->assertEquals(new LazyChoiceList($loader), $list2); + self::assertEqualsLazyChoiceList(new LazyChoiceList($loader), $list1); + self::assertEqualsLazyChoiceList(new LazyChoiceList($loader), $list2); } public function testCreateFromLoaderSameLoaderUseCache() @@ -196,8 +196,8 @@ public function testCreateFromLoaderSameLoaderUseCache() $list2 = $this->factory->createListFromLoader(ChoiceList::loader($type, new ArrayChoiceLoader())); $this->assertSame($list1, $list2); - $this->assertEquals(new LazyChoiceList(new ArrayChoiceLoader(), null), $list1); - $this->assertEquals(new LazyChoiceList(new ArrayChoiceLoader(), null), $list2); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new ArrayChoiceLoader(), null), $list1); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new ArrayChoiceLoader(), null), $list2); } public function testCreateFromLoaderDifferentLoader() @@ -213,8 +213,8 @@ public function testCreateFromLoaderSameValueClosure() $list2 = $this->factory->createListFromLoader($loader, $closure); $this->assertNotSame($list1, $list2); - $this->assertEquals(new LazyChoiceList($loader, $closure), $list1); - $this->assertEquals(new LazyChoiceList($loader, $closure), $list2); + self::assertEqualsLazyChoiceList(new LazyChoiceList($loader, $closure), $list1); + self::assertEqualsLazyChoiceList(new LazyChoiceList($loader, $closure), $list2); } public function testCreateFromLoaderSameValueClosureUseCache() @@ -226,8 +226,8 @@ public function testCreateFromLoaderSameValueClosureUseCache() $list2 = $this->factory->createListFromLoader(ChoiceList::loader($type, new ArrayChoiceLoader()), ChoiceList::value($type, function () {})); $this->assertSame($list1, $list2); - $this->assertEquals(new LazyChoiceList($loader, $closure), $list1); - $this->assertEquals(new LazyChoiceList(new ArrayChoiceLoader(), function () {}), $list2); + self::assertEqualsLazyChoiceList(new LazyChoiceList($loader, $closure), $list1); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new ArrayChoiceLoader(), function () {}), $list2); } public function testCreateFromLoaderDifferentValueClosure() @@ -249,8 +249,8 @@ public function testCreateFromLoaderSameFilterClosure() $list2 = $this->factory->createListFromLoader(ChoiceList::loader($type, new ArrayChoiceLoader()), null, $closure); $this->assertNotSame($list1, $list2); - $this->assertEquals(new LazyChoiceList(new FilterChoiceLoaderDecorator($loader, $closure)), $list1); - $this->assertEquals(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $closure)), $list2); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new FilterChoiceLoaderDecorator($loader, $closure)), $list1); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $closure)), $list2); } public function testCreateFromLoaderSameFilterClosureUseCache() @@ -261,8 +261,8 @@ public function testCreateFromLoaderSameFilterClosureUseCache() $list2 = $this->factory->createListFromLoader(ChoiceList::loader($type, new ArrayChoiceLoader()), null, $choiceFilter); $this->assertSame($list1, $list2); - $this->assertEquals(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), function () {})), $list1); - $this->assertEquals(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), function () {})), $list2); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), function () {})), $list1); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), function () {})), $list2); } public function testCreateFromLoaderDifferentFilterClosure() @@ -274,8 +274,8 @@ public function testCreateFromLoaderDifferentFilterClosure() $list2 = $this->factory->createListFromLoader(ChoiceList::loader($type, new ArrayChoiceLoader()), null, $closure2); $this->assertNotSame($list1, $list2); - $this->assertEquals(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $closure1), null), $list1); - $this->assertEquals(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $closure2), null), $list2); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $closure1), null), $list1); + self::assertEqualsLazyChoiceList(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $closure2), null), $list2); } public function testCreateViewSamePreferredChoices() diff --git a/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php b/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php index 2b1b239e58..0748011a3c 100644 --- a/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php +++ b/Tests/ChoiceList/Factory/DefaultChoiceListFactoryTest.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; use Symfony\Component\Form\ChoiceList\View\ChoiceListView; use Symfony\Component\Form\ChoiceList\View\ChoiceView; +use Symfony\Component\Form\Tests\ChoiceList\ChoiceListAssertionTrait; use Symfony\Component\Form\Tests\Fixtures\ArrayChoiceLoader; use Symfony\Component\Translation\TranslatableMessage; use Symfony\Contracts\Translation\TranslatableInterface; @@ -27,6 +28,8 @@ class DefaultChoiceListFactoryTest extends TestCase { + use ChoiceListAssertionTrait; + private \stdClass $obj1; private \stdClass $obj2; private \stdClass $obj3; @@ -261,7 +264,7 @@ public function testCreateFromLoaderWithFilter() $list = $this->factory->createListFromLoader(new ArrayChoiceLoader(), null, $filter); - $this->assertEquals(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $filter)), $list); + $this->assertEqualsLazyChoiceList(new LazyChoiceList(new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(), $filter)), $list); } public function testCreateViewFlat() diff --git a/Tests/ChoiceList/Loader/FilterChoiceLoaderDecoratorTest.php b/Tests/ChoiceList/Loader/FilterChoiceLoaderDecoratorTest.php index 5a41e5aff3..e8f51dd6b3 100644 --- a/Tests/ChoiceList/Loader/FilterChoiceLoaderDecoratorTest.php +++ b/Tests/ChoiceList/Loader/FilterChoiceLoaderDecoratorTest.php @@ -14,17 +14,20 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\FilterChoiceLoaderDecorator; +use Symfony\Component\Form\Tests\ChoiceList\ChoiceListAssertionTrait; use Symfony\Component\Form\Tests\Fixtures\ArrayChoiceLoader; class FilterChoiceLoaderDecoratorTest extends TestCase { + use ChoiceListAssertionTrait; + public function testLoadChoiceList() { $filter = fn ($choice) => 0 === $choice % 2; $loader = new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(range(1, 4)), $filter); - $this->assertEquals(new ArrayChoiceList([1 => 2, 3 => 4]), $loader->loadChoiceList()); + $this->assertEqualsArrayChoiceList(new ArrayChoiceList([1 => 2, 3 => 4]), $loader->loadChoiceList()); } public function testLoadChoiceListWithGroupedChoices() @@ -33,7 +36,7 @@ public function testLoadChoiceListWithGroupedChoices() $loader = new FilterChoiceLoaderDecorator(new ArrayChoiceLoader(['units' => range(1, 9), 'tens' => range(10, 90, 10)]), $filter); - $this->assertEquals(new ArrayChoiceList([ + $this->assertEqualsArrayChoiceList(new ArrayChoiceList([ 'units' => [ 1 => 2, 3 => 4, @@ -50,7 +53,7 @@ public function testLoadChoiceListMixedWithGroupedAndNonGroupedChoices() $choices = array_merge(range(1, 9), ['grouped' => range(10, 40, 5)]); $loader = new FilterChoiceLoaderDecorator(new ArrayChoiceLoader($choices), $filter); - $this->assertEquals(new ArrayChoiceList([ + $this->assertEqualsArrayChoiceList(new ArrayChoiceList([ 1 => 2, 3 => 4, 5 => 6, diff --git a/Tests/Command/DebugCommandTest.php b/Tests/Command/DebugCommandTest.php index cac92addbf..cc38e4b653 100644 --- a/Tests/Command/DebugCommandTest.php +++ b/Tests/Command/DebugCommandTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Command; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; use Symfony\Component\Console\Exception\InvalidArgumentException; @@ -45,14 +46,15 @@ public function testDebugDeprecatedDefaults() $this->assertEquals(0, $ret, 'Returns 0 in case of success'); $this->assertSame(<<getDisplay(true)); + TXT, + $tester->getDisplay(true) + ); } public function testDebugSingleFormType() @@ -93,12 +95,12 @@ public function testDebugSingleFormTypeNotFound() public function testDebugAmbiguousFormType() { $expectedMessage = <<expectException(InvalidArgumentException::class); $this->expectExceptionMessage($expectedMessage); @@ -125,16 +127,17 @@ public function testDebugAmbiguousFormTypeInteractive() $output = $tester->getDisplay(true); $this->assertStringMatchesFormat(<<assertEquals(0, $ret, 'Returns 0 in case of success'); $this->assertStringMatchesFormat(<<<'TXT' -Symfony\Component\Form\Tests\Command\FooType (foo) -================================================== - - ---------------- -----------%s - Info "Info" %s - ---------------- -----------%s - Required true %s - ---------------- -----------%s - Default - %s - ---------------- -----------%s - Allowed types [ %s - "string"%s - ] %s - ---------------- -----------%s - Allowed values [ %s - "bar", %s - "baz" %s - ] %s - ---------------- -----------%s - Normalizers [ %s - Closure(%s - class:%s - this: %s - file: %s - line: %s - } %s - ] %s - ---------------- -----------%s - Nested Options - %s - ---------------- -----------%s - -TXT - , $tester->getDisplay(true)); + Symfony\Component\Form\Tests\Command\FooType (foo) + ================================================== + + ---------------- -----------%s + Info "Info" %s + ---------------- -----------%s + Required true %s + ---------------- -----------%s + Default - %s + ---------------- -----------%s + Allowed types [ %s + "string"%s + ] %s + ---------------- -----------%s + Allowed values [ %s + "bar", %s + "baz" %s + ] %s + ---------------- -----------%s + Normalizers [ %s + Closure(%s + class:%s + this: %s + file: %s + line: %s + } %s + ] %s + ---------------- -----------%s + Nested Options - %s + ---------------- -----------%s + + TXT, + $tester->getDisplay(true) + ); } - /** - * @dataProvider provideCompletionSuggestions - */ + #[DataProvider('provideCompletionSuggestions')] public function testComplete(array $input, array $expectedSuggestions) { $formRegistry = new FormRegistry([], new ResolvedFormTypeFactory()); $command = new DebugCommand($formRegistry); $application = new Application(); - $application->add($command); + $application->addCommand($command); $tester = new CommandCompletionTester($application->get('debug:form')); $this->assertSame($expectedSuggestions, $tester->complete($input)); } @@ -278,7 +280,7 @@ private function createCommandTester(array $namespaces = ['Symfony\Component\For $formRegistry = new FormRegistry([], new ResolvedFormTypeFactory()); $command = new DebugCommand($formRegistry, $namespaces, $types); $application = new Application(); - $application->add($command); + $application->addCommand($command); return new CommandTester($application->find('debug:form')); } diff --git a/Tests/CompoundFormPerformanceTest.php b/Tests/CompoundFormPerformanceTest.php index b9c81f1d1e..8177dbf385 100644 --- a/Tests/CompoundFormPerformanceTest.php +++ b/Tests/CompoundFormPerformanceTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\Group; use Symfony\Component\Form\Test\FormPerformanceTestCase; /** @@ -20,9 +21,8 @@ class CompoundFormPerformanceTest extends FormPerformanceTestCase { /** * Create a compound form multiple times, as happens in a collection form. - * - * @group benchmark */ + #[Group('benchmark')] public function testArrayBasedForm() { $this->setMaxRunningTime(1); diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 882e73034c..13773b2a06 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Exception\AlreadySubmittedException; @@ -585,9 +586,7 @@ public static function requestMethodProvider(): array ]; } - /** - * @dataProvider requestMethodProvider - */ + #[DataProvider('requestMethodProvider')] public function testSubmitPostOrPutRequest($method) { $path = tempnam(sys_get_temp_dir(), 'sf'); @@ -633,9 +632,7 @@ public function testSubmitPostOrPutRequest($method) unlink($path); } - /** - * @dataProvider requestMethodProvider - */ + #[DataProvider('requestMethodProvider')] public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) { $path = tempnam(sys_get_temp_dir(), 'sf'); @@ -681,9 +678,7 @@ public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) unlink($path); } - /** - * @dataProvider requestMethodProvider - */ + #[DataProvider('requestMethodProvider')] public function testSubmitPostOrPutRequestWithSingleChildForm($method) { $path = tempnam(sys_get_temp_dir(), 'sf'); @@ -718,9 +713,7 @@ public function testSubmitPostOrPutRequestWithSingleChildForm($method) unlink($path); } - /** - * @dataProvider requestMethodProvider - */ + #[DataProvider('requestMethodProvider')] public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method) { $path = tempnam(sys_get_temp_dir(), 'sf'); diff --git a/Tests/Console/Descriptor/AbstractDescriptorTestCase.php b/Tests/Console/Descriptor/AbstractDescriptorTestCase.php index 456b433eee..f956c7475b 100644 --- a/Tests/Console/Descriptor/AbstractDescriptorTestCase.php +++ b/Tests/Console/Descriptor/AbstractDescriptorTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Console\Descriptor; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\BufferedOutput; @@ -41,7 +42,7 @@ protected function tearDown(): void putenv($this->colSize ? 'COLUMNS='.$this->colSize : 'COLUMNS'); } - /** @dataProvider getDescribeDefaultsTestData */ + #[DataProvider('getDescribeDefaultsTestData')] public function testDescribeDefaults($object, array $options, $fixtureName) { $describedObject = $this->getObjectDescription($object, $options); @@ -54,7 +55,7 @@ public function testDescribeDefaults($object, array $options, $fixtureName) } } - /** @dataProvider getDescribeResolvedFormTypeTestData */ + #[DataProvider('getDescribeResolvedFormTypeTestData')] public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, array $options, $fixtureName) { $describedObject = $this->getObjectDescription($type, $options); @@ -67,7 +68,7 @@ public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, ar } } - /** @dataProvider getDescribeOptionTestData */ + #[DataProvider('getDescribeOptionTestData')] public function testDescribeOption(OptionsResolver $optionsResolver, array $options, $fixtureName) { $describedObject = $this->getObjectDescription($optionsResolver, $options); diff --git a/Tests/DependencyInjection/FormPassTest.php b/Tests/DependencyInjection/FormPassTest.php index f0ccd3f095..1e951ae430 100644 --- a/Tests/DependencyInjection/FormPassTest.php +++ b/Tests/DependencyInjection/FormPassTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\DependencyInjection; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; @@ -60,7 +61,7 @@ public function testAddTaggedTypes() $extDefinition = $container->getDefinition('form.extension'); $locator = $extDefinition->getArgument(0); - $this->assertTrue(!$locator->isPublic() || $locator->isPrivate()); + $this->assertTrue($locator->isPrivate()); $this->assertEquals( (new Definition(ServiceLocator::class, [[ __CLASS__.'_Type1' => new ServiceClosureArgument(new Reference('my.type1')), @@ -115,9 +116,7 @@ public function testAddTaggedTypesToCsrfTypeExtension() $this->assertSame([__CLASS__.'_Type1' => 'the_token_id'], $csrfDefinition->getArgument(7)); } - /** - * @dataProvider addTaggedTypeExtensionsDataProvider - */ + #[DataProvider('addTaggedTypeExtensionsDataProvider')] public function testAddTaggedTypeExtensions(array $extensions, array $expectedRegisteredExtensions, array $parameters = []) { $container = $this->createContainerBuilder(); @@ -280,9 +279,7 @@ public function testAddTaggedGuessers() ); } - /** - * @dataProvider privateTaggedServicesProvider - */ + #[DataProvider('privateTaggedServicesProvider')] public function testPrivateTaggedServices($id, $class, $tagName, callable $assertion, array $tagAttributes = []) { $formPass = new FormPass(); diff --git a/Tests/EnumFormTypeGuesserTest.php b/Tests/EnumFormTypeGuesserTest.php new file mode 100644 index 0000000000..f0a04c7f5f --- /dev/null +++ b/Tests/EnumFormTypeGuesserTest.php @@ -0,0 +1,208 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Form\EnumFormTypeGuesser; +use Symfony\Component\Form\Extension\Core\Type\EnumType as FormEnumType; +use Symfony\Component\Form\Guess\Guess; +use Symfony\Component\Form\Guess\TypeGuess; +use Symfony\Component\Form\Guess\ValueGuess; +use Symfony\Component\Form\Tests\Fixtures\BackedEnumFormTypeGuesserCaseEnum; +use Symfony\Component\Form\Tests\Fixtures\EnumFormTypeGuesserCase; +use Symfony\Component\Form\Tests\Fixtures\EnumFormTypeGuesserCaseEnum; + +class EnumFormTypeGuesserTest extends TestCase +{ + #[DataProvider('provideGuessTypeCases')] + public function testGuessType(?TypeGuess $expectedTypeGuess, string $class, string $property) + { + $typeGuesser = new EnumFormTypeGuesser(); + + $typeGuess = $typeGuesser->guessType($class, $property); + + self::assertEquals($expectedTypeGuess, $typeGuess); + } + + #[DataProvider('provideGuessRequiredCases')] + public function testGuessRequired(?ValueGuess $expectedValueGuess, string $class, string $property) + { + $typeGuesser = new EnumFormTypeGuesser(); + + $valueGuess = $typeGuesser->guessRequired($class, $property); + + self::assertEquals($expectedValueGuess, $valueGuess); + } + + public static function provideGuessTypeCases(): iterable + { + yield 'Undefined class' => [ + null, + 'UndefinedClass', + 'undefinedProperty', + ]; + + yield 'Undefined property' => [ + null, + EnumFormTypeGuesserCase::class, + 'undefinedProperty', + ]; + + yield 'Undefined enum' => [ + null, + EnumFormTypeGuesserCase::class, + 'undefinedEnum', + ]; + + yield 'Non-enum property' => [ + null, + EnumFormTypeGuesserCase::class, + 'string', + ]; + + yield 'Enum property' => [ + new TypeGuess( + FormEnumType::class, + [ + 'class' => EnumFormTypeGuesserCaseEnum::class, + ], + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'enum', + ]; + + yield 'Nullable enum property' => [ + new TypeGuess( + FormEnumType::class, + [ + 'class' => EnumFormTypeGuesserCaseEnum::class, + ], + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'nullableEnum', + ]; + + yield 'Backed enum property' => [ + new TypeGuess( + FormEnumType::class, + [ + 'class' => BackedEnumFormTypeGuesserCaseEnum::class, + ], + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'backedEnum', + ]; + + yield 'Nullable backed enum property' => [ + new TypeGuess( + FormEnumType::class, + [ + 'class' => BackedEnumFormTypeGuesserCaseEnum::class, + ], + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'nullableBackedEnum', + ]; + + yield 'Enum union property' => [ + null, + EnumFormTypeGuesserCase::class, + 'enumUnion', + ]; + + yield 'Enum intersection property' => [ + null, + EnumFormTypeGuesserCase::class, + 'enumIntersection', + ]; + } + + public static function provideGuessRequiredCases(): iterable + { + yield 'Unknown class' => [ + null, + 'UndefinedClass', + 'undefinedProperty', + ]; + + yield 'Unknown property' => [ + null, + EnumFormTypeGuesserCase::class, + 'undefinedProperty', + ]; + + yield 'Undefined enum' => [ + null, + EnumFormTypeGuesserCase::class, + 'undefinedEnum', + ]; + + yield 'Non-enum property' => [ + null, + EnumFormTypeGuesserCase::class, + 'string', + ]; + + yield 'Enum property' => [ + new ValueGuess( + true, + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'enum', + ]; + + yield 'Nullable enum property' => [ + new ValueGuess( + false, + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'nullableEnum', + ]; + + yield 'Backed enum property' => [ + new ValueGuess( + true, + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'backedEnum', + ]; + + yield 'Nullable backed enum property' => [ + new ValueGuess( + false, + Guess::HIGH_CONFIDENCE, + ), + EnumFormTypeGuesserCase::class, + 'nullableBackedEnum', + ]; + + yield 'Enum union property' => [ + null, + EnumFormTypeGuesserCase::class, + 'enumUnion', + ]; + + yield 'Enum intersection property' => [ + null, + EnumFormTypeGuesserCase::class, + 'enumIntersection', + ]; + } +} diff --git a/Tests/Extension/Core/DataMapper/DataMapperTest.php b/Tests/Extension/Core/DataMapper/DataMapperTest.php index 1a8f2678dd..5ca81ac875 100644 --- a/Tests/Extension/Core/DataMapper/DataMapperTest.php +++ b/Tests/Extension/Core/DataMapper/DataMapperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Extension\Core\DataAccessor\PropertyPathAccessor; @@ -317,9 +318,7 @@ public function testMapFormsToUninitializedProperties() self::assertSame('BMW', $car->engine); } - /** - * @dataProvider provideDate - */ + #[DataProvider('provideDate')] public function testMapFormsToDataDoesNotChangeEqualDateTimeInstance($date) { $article = []; diff --git a/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php b/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php index 4c6f74925d..5eda911b57 100644 --- a/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\Exception\TransformationFailedException; @@ -41,9 +42,7 @@ public static function transformProvider(): array ]; } - /** - * @dataProvider transformProvider - */ + #[DataProvider('transformProvider')] public function testTransform($in, $out, $inWithNull, $outWithNull) { $this->assertSame($out, $this->transformer->transform($in)); @@ -62,9 +61,7 @@ public static function reverseTransformProvider() ]; } - /** - * @dataProvider reverseTransformProvider - */ + #[DataProvider('reverseTransformProvider')] public function testReverseTransform($in, $out, $inWithNull, $outWithNull) { $this->assertSame($out, $this->transformer->reverseTransform($in)); @@ -81,9 +78,7 @@ public static function reverseTransformExpectsStringOrNullProvider() ]; } - /** - * @dataProvider reverseTransformExpectsStringOrNullProvider - */ + #[DataProvider('reverseTransformExpectsStringOrNullProvider')] public function testReverseTransformExpectsStringOrNull($value) { $this->expectException(TransformationFailedException::class); diff --git a/Tests/Extension/Core/DataTransformer/DateIntervalToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateIntervalToStringTransformerTest.php index 1a978737f9..d8545d8de7 100644 --- a/Tests/Extension/Core/DataTransformer/DateIntervalToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateIntervalToStringTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Core\DataTransformer\DateIntervalToStringTransformer; @@ -52,9 +53,7 @@ public static function dataProviderDate(): array ]; } - /** - * @dataProvider dataProviderISO - */ + #[DataProvider('dataProviderISO')] public function testTransform($format, $output, $input) { $transformer = new DateIntervalToStringTransformer($format); @@ -75,9 +74,7 @@ public function testTransformExpectsDateTime() $transformer->transform('1234'); } - /** - * @dataProvider dataProviderISO - */ + #[DataProvider('dataProviderISO')] public function testReverseTransform($format, $input, $output) { $reverseTransformer = new DateIntervalToStringTransformer($format, true); @@ -85,9 +82,7 @@ public function testReverseTransform($format, $input, $output) $this->assertDateIntervalEquals($interval, $reverseTransformer->reverseTransform($input)); } - /** - * @dataProvider dataProviderDate - */ + #[DataProvider('dataProviderDate')] public function testReverseTransformDateString($format, $input, $output) { $reverseTransformer = new DateIntervalToStringTransformer($format, true); diff --git a/Tests/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformerTest.php index 04f8e74a4a..8de1599f91 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeImmutableToDateTimeTransformerTest.php @@ -11,15 +11,14 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeImmutableToDateTimeTransformer; class DateTimeImmutableToDateTimeTransformerTest extends TestCase { - /** - * @dataProvider provider - */ + #[DataProvider('provider')] public function testTransform(\DateTime $expectedOutput, \DateTimeImmutable $input) { $transformer = new DateTimeImmutableToDateTimeTransformer(); @@ -61,9 +60,7 @@ public function testTransformFail() $transformer->transform(new \DateTime()); } - /** - * @dataProvider provider - */ + #[DataProvider('provider')] public function testReverseTransform(\DateTime $input, \DateTimeImmutable $expectedOutput) { $transformer = new DateTimeImmutableToDateTimeTransformer(); diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php index f2fb15cf0b..cdd7fd4738 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToHtml5LocalDateTimeTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToHtml5LocalDateTimeTransformer; @@ -56,9 +57,7 @@ public static function reverseTransformProvider(): array ]; } - /** - * @dataProvider transformProvider - */ + #[DataProvider('transformProvider')] public function testTransform($fromTz, $toTz, $from, $to, bool $withSeconds) { $transformer = new DateTimeToHtml5LocalDateTimeTransformer($fromTz, $toTz, $withSeconds); @@ -66,9 +65,7 @@ public function testTransform($fromTz, $toTz, $from, $to, bool $withSeconds) $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null)); } - /** - * @dataProvider transformProvider - */ + #[DataProvider('transformProvider')] public function testTransformDateTimeImmutable($fromTz, $toTz, $from, $to, bool $withSeconds) { $transformer = new DateTimeToHtml5LocalDateTimeTransformer($fromTz, $toTz, $withSeconds); @@ -83,9 +80,7 @@ public function testTransformRequiresValidDateTime() $transformer->transform('2010-01-01'); } - /** - * @dataProvider reverseTransformProvider - */ + #[DataProvider('reverseTransformProvider')] public function testReverseTransform($toTz, $fromTz, $to, $from) { $transformer = new DateTimeToHtml5LocalDateTimeTransformer($toTz, $fromTz); diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index d0207bbd05..b66716769e 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer; @@ -49,7 +52,9 @@ protected function setUp(): void protected function tearDown(): void { - \Locale::setDefault($this->defaultLocale); + if (isset($this->defaultLocale)) { + \Locale::setDefault($this->defaultLocale); + } if (\extension_loaded('intl')) { ini_set('intl.use_exceptions', $this->initialTestCaseUseException); @@ -90,9 +95,7 @@ public static function dataProvider() ]; } - /** - * @dataProvider dataProvider - */ + #[DataProvider('dataProvider')] public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input) { IntlTestHelper::requireFullIntl($this, '59.1'); @@ -206,9 +209,7 @@ public function testTransformWrapsIntlErrors() // $transformer->transform(1.5); } - /** - * @dataProvider dataProvider - */ + #[DataProvider('dataProvider')] public function testReverseTransform($dateFormat, $timeFormat, $pattern, $input, $output) { $transformer = new DateTimeToLocalizedStringTransformer( @@ -341,10 +342,8 @@ public function testReverseTransformFiveDigitYearsWithTimestamp() $transformer->reverseTransform('20107-03-21 12:34:56'); } - /** - * @requires extension intl - * @requires PHP < 8.5 - */ + #[RequiresPhpExtension('intl')] + #[RequiresPhp('< 8.5')] public function testReverseTransformWrapsIntlErrorsWithErrorLevel() { $errorLevel = ini_set('intl.error_level', \E_WARNING); @@ -358,9 +357,7 @@ public function testReverseTransformWrapsIntlErrorsWithErrorLevel() } } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testReverseTransformWrapsIntlErrorsWithExceptions() { $initialUseExceptions = ini_set('intl.use_exceptions', 1); @@ -374,10 +371,8 @@ public function testReverseTransformWrapsIntlErrorsWithExceptions() } } - /** - * @requires extension intl - * @requires PHP < 8.5 - */ + #[RequiresPhpExtension('intl')] + #[RequiresPhp('< 8.5')] public function testReverseTransformWrapsIntlErrorsWithExceptionsAndErrorLevel() { $initialUseExceptions = ini_set('intl.use_exceptions', 1); diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index c69ba31be9..16115af213 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer; @@ -57,9 +58,7 @@ public static function reverseTransformProvider(): array ]); } - /** - * @dataProvider transformProvider - */ + #[DataProvider('transformProvider')] public function testTransform($fromTz, $toTz, $from, $to) { $transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz); @@ -67,9 +66,7 @@ public function testTransform($fromTz, $toTz, $from, $to) $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null)); } - /** - * @dataProvider transformProvider - */ + #[DataProvider('transformProvider')] public function testTransformDateTimeImmutable($fromTz, $toTz, $from, $to) { $transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz); @@ -84,9 +81,7 @@ public function testTransformRequiresValidDateTime() $transformer->transform('2010-01-01'); } - /** - * @dataProvider reverseTransformProvider - */ + #[DataProvider('reverseTransformProvider')] public function testReverseTransform($toTz, $fromTz, $to, $from) { $transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz); @@ -113,9 +108,7 @@ public function testReverseTransformWithNonExistingDate() $transformer->reverseTransform('2010-04-31T04:05Z'); } - /** - * @dataProvider invalidDateStringProvider - */ + #[DataProvider('invalidDateStringProvider')] public function testReverseTransformExpectsValidDateString($date) { $this->expectException(TransformationFailedException::class); diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php index f7ef667e76..a2412c4f85 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; @@ -64,9 +65,7 @@ public static function dataProvider(): array ]; } - /** - * @dataProvider dataProvider - */ + #[DataProvider('dataProvider')] public function testTransform($format, $output, $input) { $transformer = new DateTimeToStringTransformer('UTC', 'UTC', $format); @@ -114,9 +113,7 @@ public function testTransformExpectsDateTime() $transformer->transform('1234'); } - /** - * @dataProvider dataProvider - */ + #[DataProvider('dataProvider')] public function testReverseTransform($format, $input, $output) { $reverseTransformer = new DateTimeToStringTransformer('UTC', 'UTC', $format); diff --git a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php index 92443e2011..01fa5282f8 100644 --- a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; @@ -82,9 +83,7 @@ public static function transformWithRoundingProvider() ]; } - /** - * @dataProvider transformWithRoundingProvider - */ + #[DataProvider('transformWithRoundingProvider')] public function testTransformWithRounding($input, $output, $roundingMode) { $transformer = new IntegerToLocalizedStringTransformer(null, $roundingMode); @@ -178,9 +177,7 @@ public static function reverseTransformWithRoundingProvider() ]; } - /** - * @dataProvider reverseTransformWithRoundingProvider - */ + #[DataProvider('reverseTransformWithRoundingProvider')] public function testReverseTransformWithRounding($input, $output, $roundingMode) { $transformer = new IntegerToLocalizedStringTransformer(null, $roundingMode); @@ -204,9 +201,7 @@ public function testReverseTransformExpectsValidNumber() $transformer->reverseTransform('foo'); } - /** - * @dataProvider floatNumberProvider - */ + #[DataProvider('floatNumberProvider')] public function testReverseTransformExpectsInteger($number, $locale) { $this->expectException(TransformationFailedException::class); diff --git a/Tests/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformerTest.php index ca80a21031..ac9d23582e 100644 --- a/Tests/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/IntlTimeZoneToStringTransformerTest.php @@ -11,13 +11,12 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\IntlTimeZoneToStringTransformer; -/** - * @requires extension intl - */ +#[RequiresPhpExtension('intl')] class IntlTimeZoneToStringTransformerTest extends TestCase { public function testSingle() diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index f22fa5da3f..be50f9a1d1 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; @@ -56,9 +59,7 @@ public static function provideTransformations() ]; } - /** - * @dataProvider provideTransformations - */ + #[DataProvider('provideTransformations')] public function testTransform($from, $to, $locale) { // Since we test against other locales, we need the full implementation @@ -82,9 +83,7 @@ public static function provideTransformationsWithGrouping() ]; } - /** - * @dataProvider provideTransformationsWithGrouping - */ + #[DataProvider('provideTransformationsWithGrouping')] public function testTransformWithGrouping($from, $to, $locale) { // Since we test against other locales, we need the full implementation @@ -199,9 +198,7 @@ public static function transformWithRoundingProvider() ]; } - /** - * @dataProvider transformWithRoundingProvider - */ + #[DataProvider('transformWithRoundingProvider')] public function testTransformWithRounding($scale, $input, $output, $roundingMode) { // Since we test against "de_AT", we need the full implementation @@ -226,9 +223,7 @@ public function testTransformDoesNotRoundIfNoScale() $this->assertEquals('1234,547', $transformer->transform(1234.547)); } - /** - * @dataProvider provideTransformations - */ + #[DataProvider('provideTransformations')] public function testReverseTransform($to, $from, $locale) { // Since we test against other locales, we need the full implementation @@ -241,9 +236,7 @@ public function testReverseTransform($to, $from, $locale) $this->assertEquals($to, $transformer->reverseTransform($from)); } - /** - * @dataProvider provideTransformationsWithGrouping - */ + #[DataProvider('provideTransformationsWithGrouping')] public function testReverseTransformWithGrouping($to, $from, $locale) { // Since we test against other locales, we need the full implementation @@ -376,9 +369,7 @@ public static function reverseTransformWithRoundingProvider() ]; } - /** - * @dataProvider reverseTransformWithRoundingProvider - */ + #[DataProvider('reverseTransformWithRoundingProvider')] public function testReverseTransformWithRounding($scale, $input, $output, $roundingMode) { $transformer = new NumberToLocalizedStringTransformer($scale, null, $roundingMode); @@ -518,10 +509,9 @@ public function testReverseTransformExpectsValidNumber() } /** - * @dataProvider nanRepresentationProvider - * * @see https://github.com/symfony/symfony/issues/3161 */ + #[DataProvider('nanRepresentationProvider')] public function testReverseTransformDisallowsNaN($nan) { $this->expectException(TransformationFailedException::class); @@ -645,9 +635,7 @@ public function testReverseTransformSmallInt() $this->assertSame(1.0, $transformer->reverseTransform('1')); } - /** - * @dataProvider eNotationProvider - */ + #[DataProvider('eNotationProvider')] public function testReverseTransformENotation($output, $input) { IntlTestHelper::requireFullIntl($this); @@ -659,10 +647,8 @@ public function testReverseTransformENotation($output, $input) $this->assertSame($output, $transformer->reverseTransform($input)); } - /** - * @requires extension intl - * @requires PHP < 8.5 - */ + #[RequiresPhpExtension('intl')] + #[RequiresPhp('< 8.5')] public function testReverseTransformWrapsIntlErrorsWithErrorLevel() { $errorLevel = ini_set('intl.error_level', \E_WARNING); @@ -676,9 +662,7 @@ public function testReverseTransformWrapsIntlErrorsWithErrorLevel() } } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testReverseTransformWrapsIntlErrorsWithExceptions() { $initialUseExceptions = ini_set('intl.use_exceptions', 1); @@ -692,10 +676,8 @@ public function testReverseTransformWrapsIntlErrorsWithExceptions() } } - /** - * @requires extension intl - * @requires PHP < 8.5 - */ + #[RequiresPhpExtension('intl')] + #[RequiresPhp('< 8.5')] public function testReverseTransformWrapsIntlErrorsWithExceptionsAndErrorLevel() { $initialUseExceptions = ini_set('intl.use_exceptions', 1); diff --git a/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php index ca935d564b..8c15a49f18 100644 --- a/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresPhp; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; @@ -191,9 +194,7 @@ public static function reverseTransformWithRoundingProvider(): array ]; } - /** - * @dataProvider reverseTransformWithRoundingProvider - */ + #[DataProvider('reverseTransformWithRoundingProvider')] public function testReverseTransformWithRounding($type, $scale, $input, $output, $roundingMode) { $transformer = new PercentToLocalizedStringTransformer($scale, $type, $roundingMode); @@ -364,9 +365,7 @@ public function testReverseTransformDisallowsCenteredExtraCharacters() $transformer->reverseTransform('12foo3'); } - /** - * @requires extension mbstring - */ + #[RequiresPhpExtension('mbstring')] public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() { $this->expectException(TransformationFailedException::class); @@ -390,9 +389,7 @@ public function testReverseTransformDisallowsTrailingExtraCharacters() $transformer->reverseTransform('123foo'); } - /** - * @requires extension mbstring - */ + #[RequiresPhpExtension('mbstring')] public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte() { $this->expectException(TransformationFailedException::class); @@ -487,10 +484,8 @@ public function testReverseTransformForHtml5FormatWithScale() $this->assertEquals(0.1234, $transformer->reverseTransform('12.34')); } - /** - * @requires extension intl - * @requires PHP < 8.5 - */ + #[RequiresPhpExtension('intl')] + #[RequiresPhp('< 8.5')] public function testReverseTransformWrapsIntlErrorsWithErrorLevel() { $errorLevel = ini_set('intl.error_level', \E_WARNING); @@ -504,9 +499,7 @@ public function testReverseTransformWrapsIntlErrorsWithErrorLevel() } } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testReverseTransformWrapsIntlErrorsWithExceptions() { $initialUseExceptions = ini_set('intl.use_exceptions', 1); @@ -520,10 +513,8 @@ public function testReverseTransformWrapsIntlErrorsWithExceptions() } } - /** - * @requires extension intl - * @requires PHP < 8.5 - */ + #[RequiresPhpExtension('intl')] + #[RequiresPhp('< 8.5')] public function testReverseTransformWrapsIntlErrorsWithExceptionsAndErrorLevel() { $initialUseExceptions = ini_set('intl.use_exceptions', 1); diff --git a/Tests/Extension/Core/DataTransformer/StringToFloatTransformerTest.php b/Tests/Extension/Core/DataTransformer/StringToFloatTransformerTest.php index aaea8b2984..9fa8c500e1 100644 --- a/Tests/Extension/Core/DataTransformer/StringToFloatTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/StringToFloatTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\StringToFloatTransformer; @@ -28,9 +29,7 @@ public static function provideTransformations(): array ]; } - /** - * @dataProvider provideTransformations - */ + #[DataProvider('provideTransformations')] public function testTransform($from, $to) { $transformer = new StringToFloatTransformer(); @@ -68,9 +67,7 @@ public static function provideReverseTransformations(): array ]; } - /** - * @dataProvider provideReverseTransformations - */ + #[DataProvider('provideReverseTransformations')] public function testReverseTransform($from, $to, ?int $scale = null) { $transformer = new StringToFloatTransformer($scale); diff --git a/Tests/Extension/Core/DataTransformer/UlidToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/UlidToStringTransformerTest.php index 7978941b5d..adf70d86be 100644 --- a/Tests/Extension/Core/DataTransformer/UlidToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/UlidToStringTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\UlidToStringTransformer; @@ -25,9 +26,7 @@ public static function provideValidUlid() ]; } - /** - * @dataProvider provideValidUlid - */ + #[DataProvider('provideValidUlid')] public function testTransform($output, $input) { $transformer = new UlidToStringTransformer(); @@ -53,9 +52,7 @@ public function testTransformExpectsUlid() $transformer->transform('1234'); } - /** - * @dataProvider provideValidUlid - */ + #[DataProvider('provideValidUlid')] public function testReverseTransform($input, $output) { $reverseTransformer = new UlidToStringTransformer(); diff --git a/Tests/Extension/Core/DataTransformer/WeekToArrayTransformerTest.php b/Tests/Extension/Core/DataTransformer/WeekToArrayTransformerTest.php index 67e7f7a360..e73dd4978a 100644 --- a/Tests/Extension/Core/DataTransformer/WeekToArrayTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/WeekToArrayTransformerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\DataTransformer\WeekToArrayTransformer; @@ -31,9 +32,7 @@ public function testTransformEmpty() $this->assertSame(['year' => null, 'week' => null], $transformer->transform(null)); } - /** - * @dataProvider transformationFailuresProvider - */ + #[DataProvider('transformationFailuresProvider')] public function testTransformationFailures($input, string $message) { $this->expectException(TransformationFailedException::class); @@ -89,9 +88,7 @@ public function testReverseTransformEmpty() $this->assertNull($transformer->reverseTransform([])); } - /** - * @dataProvider reverseTransformationFailuresProvider - */ + #[DataProvider('reverseTransformationFailuresProvider')] public function testReverseTransformFailures($input, string $message) { $this->expectException(TransformationFailedException::class); diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 038ca9c2ea..09483a4b10 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; @@ -20,9 +21,7 @@ class FixUrlProtocolListenerTest extends TestCase { - /** - * @dataProvider provideUrlToFix - */ + #[DataProvider('provideUrlToFix')] public function testFixUrl($data) { $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); @@ -46,9 +45,7 @@ public static function provideUrlToFix() ]; } - /** - * @dataProvider provideUrlToSkip - */ + #[DataProvider('provideUrlToSkip')] public function testSkipUrl($url) { $form = new Form(new FormConfigBuilder('name', null, new EventDispatcher())); diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTestCase.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTestCase.php index 7070db995b..a90a11d1ac 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTestCase.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTestCase.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; @@ -56,9 +57,7 @@ public static function getBooleanMatrix2() abstract protected function getData(array $data); - /** - * @dataProvider getBooleanMatrix1 - */ + #[DataProvider('getBooleanMatrix1')] public function testAddExtraEntriesIfAllowAdd($allowDelete) { $originalData = $this->getData([1 => 'second']); @@ -80,9 +79,7 @@ public function testAddExtraEntriesIfAllowAdd($allowDelete) $this->assertEquals($newData, $event->getData()); } - /** - * @dataProvider getBooleanMatrix1 - */ + #[DataProvider('getBooleanMatrix1')] public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allowDelete) { $originalData = $this->getData([1 => 'first']); @@ -104,9 +101,7 @@ public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allow $this->assertEquals($this->getData([1 => 'first', 2 => 'second']), $event->getData()); } - /** - * @dataProvider getBooleanMatrix1 - */ + #[DataProvider('getBooleanMatrix1')] public function testDoNothingIfNotAllowAdd($allowDelete) { $originalDataArray = [1 => 'second']; @@ -129,9 +124,7 @@ public function testDoNothingIfNotAllowAdd($allowDelete) $this->assertEquals($this->getData($originalDataArray), $event->getData()); } - /** - * @dataProvider getBooleanMatrix1 - */ + #[DataProvider('getBooleanMatrix1')] public function testRemoveMissingEntriesIfAllowDelete($allowAdd) { $originalData = $this->getData([0 => 'first', 1 => 'second', 2 => 'third']); @@ -153,9 +146,7 @@ public function testRemoveMissingEntriesIfAllowDelete($allowAdd) $this->assertEquals($newData, $event->getData()); } - /** - * @dataProvider getBooleanMatrix1 - */ + #[DataProvider('getBooleanMatrix1')] public function testDoNothingIfNotAllowDelete($allowAdd) { $originalDataArray = [0 => 'first', 1 => 'second', 2 => 'third']; @@ -178,9 +169,7 @@ public function testDoNothingIfNotAllowDelete($allowAdd) $this->assertEquals($this->getData($originalDataArray), $event->getData()); } - /** - * @dataProvider getBooleanMatrix2 - */ + #[DataProvider('getBooleanMatrix2')] public function testRequireArrayOrTraversable($allowAdd, $allowDelete) { $this->expectException(UnexpectedTypeException::class); @@ -205,9 +194,7 @@ public function testDealWithNullData() $this->assertSame($originalData, $event->getData()); } - /** - * @dataProvider getBooleanMatrix1 - */ + #[DataProvider('getBooleanMatrix1')] public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) { $originalData = null; @@ -223,9 +210,7 @@ public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) $this->assertSame($newData, $event->getData()); } - /** - * @dataProvider getBooleanMatrix1 - */ + #[DataProvider('getBooleanMatrix1')] public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete) { $originalData = null; diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 390f6b04a6..12d8479adf 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Event\PostSetDataEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; @@ -43,35 +44,6 @@ protected function getBuilder($name = 'name') return new FormBuilder($name, null, new EventDispatcher(), $this->factory); } - /** - * @group legacy - */ - public function testPreSetDataResizesForm() - { - $this->builder->add($this->getBuilder('0')); - $this->builder->add($this->getBuilder('1')); - $this->builder->addEventSubscriber(new class(TextType::class, ['attr' => ['maxlength' => 10]], false, false) extends ResizeFormListener { - public function preSetData(FormEvent $event): void - { - parent::preSetData($event); - } - }); - - $form = $this->builder->getForm(); - - $this->assertTrue($form->has('0')); - - // initialize the form - $form->setData([1 => 'string', 2 => 'string']); - - $this->assertFalse($form->has('0')); - $this->assertTrue($form->has('1')); - $this->assertTrue($form->has('2')); - - $this->assertSame('string', $form->get('1')->getData()); - $this->assertSame('string', $form->get('2')->getData()); - } - public function testPostSetDataResizesForm() { $this->builder->add($this->getBuilder('0')); @@ -93,54 +65,19 @@ public function testPostSetDataResizesForm() $this->assertSame('string', $form->get('2')->getData()); } - /** - * @group legacy - */ - public function testPreSetDataRequiresArrayOrTraversable() - { - $this->expectException(UnexpectedTypeException::class); - $data = 'no array or traversable'; - $event = new FormEvent($this->builder->getForm(), $data); - $listener = new class(TextType::class, [], false, false) extends ResizeFormListener { - public function preSetData(FormEvent $event): void - { - parent::preSetData($event); - } - }; - $listener->preSetData($event); - } - public function testPostSetDataRequiresArrayOrTraversable() { $this->expectException(UnexpectedTypeException::class); $data = 'no array or traversable'; - $event = new FormEvent($this->builder->getForm(), $data); + $event = new PostSetDataEvent($this->builder->getForm(), $data); $listener = new ResizeFormListener(TextType::class, [], false, false); $listener->postSetData($event); } - /** - * @group legacy - */ - public function testPreSetDataDealsWithNullData() - { - $data = null; - $event = new FormEvent($this->builder->getForm(), $data); - $listener = new class(TextType::class, [], false, false) extends ResizeFormListener { - public function preSetData(FormEvent $event): void - { - parent::preSetData($event); - } - }; - $listener->preSetData($event); - - $this->assertSame(0, $this->builder->count()); - } - public function testPostSetDataDealsWithNullData() { $data = null; - $event = new FormEvent($this->builder->getForm(), $data); + $event = new PostSetDataEvent($this->builder->getForm(), $data); $listener = new ResizeFormListener(TextType::class, [], false, false); $listener->postSetData($event); diff --git a/Tests/Extension/Core/Type/CheckboxTypeTest.php b/Tests/Extension/Core/Type/CheckboxTypeTest.php index 69fd0fd601..7601d3743a 100644 --- a/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; @@ -140,9 +141,7 @@ public function testSubmitWithEmptyValueAndTrueChecked() $this->assertSame('', $form->getViewData()); } - /** - * @dataProvider provideCustomModelTransformerData - */ + #[DataProvider('provideCustomModelTransformerData')] public function testCustomModelTransformer($data, $checked) { // present a binary status field as a checkbox @@ -171,9 +170,7 @@ public static function provideCustomModelTransformerData(): array ]; } - /** - * @dataProvider provideCustomFalseValues - */ + #[DataProvider('provideCustomFalseValues')] public function testCustomFalseValues($falseValue) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php b/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php index 3616a139c1..e73a97351d 100644 --- a/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\Group; use Symfony\Component\Form\Test\FormPerformanceTestCase; /** @@ -21,9 +22,8 @@ class ChoiceTypePerformanceTest extends FormPerformanceTestCase /** * This test case is realistic in collection forms where each * row contains the same choice field. - * - * @group benchmark */ + #[Group('benchmark')] public function testSameChoiceFieldCreatedMultipleTimes() { $this->setMaxRunningTime(1); diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 977a8707c3..99be68fe33 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView; use Symfony\Component\Form\ChoiceList\View\ChoiceView; @@ -1671,9 +1672,7 @@ public function testPlaceholderIsEmptyStringByDefaultIfNotRequired() $this->assertSame('', $view->vars['placeholder']); } - /** - * @dataProvider getOptionsWithPlaceholder - */ + #[DataProvider('getOptionsWithPlaceholder')] public function testPassPlaceholderToView($multiple, $expanded, $required, $placeholder, $placeholderViewValue, $placeholderAttr, $placeholderAttrViewValue) { $view = $this->factory->create(static::TESTED_TYPE, null, [ @@ -1691,9 +1690,7 @@ public function testPassPlaceholderToView($multiple, $expanded, $required, $plac $this->assertFalse($view->vars['placeholder_in_choices']); } - /** - * @dataProvider getOptionsWithPlaceholder - */ + #[DataProvider('getOptionsWithPlaceholder')] public function testDontPassPlaceholderIfContainedInChoices($multiple, $expanded, $required, $placeholder, $placeholderViewValue, $placeholderAttr, $placeholderAttrViewValue) { $view = $this->factory->create(static::TESTED_TYPE, null, [ @@ -1946,9 +1943,7 @@ public function testCustomChoiceTypeDoesNotInheritChoiceLabels() $this->assertNull($form->get('subChoice')->getConfig()->getOption('choice_label')); } - /** - * @dataProvider invalidNestedValueTestMatrix - */ + #[DataProvider('invalidNestedValueTestMatrix')] public function testSubmitInvalidNestedValue($multiple, $expanded, $submissionData) { $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -2114,9 +2109,7 @@ public function testSubFormTranslationDomain() $this->assertSame('choice_translation_domain', $form->children[1]->vars['translation_domain']); } - /** - * @dataProvider provideTrimCases - */ + #[DataProvider('provideTrimCases')] public function testTrimIsDisabled($multiple, $expanded) { $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -2141,9 +2134,7 @@ public function testTrimIsDisabled($multiple, $expanded) } } - /** - * @dataProvider provideTrimCases - */ + #[DataProvider('provideTrimCases')] public function testSubmitValueWithWhiteSpace($multiple, $expanded) { $valueWhitWhiteSpace = '1 '; @@ -2172,9 +2163,7 @@ public static function provideTrimCases() ]; } - /** - * @dataProvider expandedIsEmptyWhenNoRealChoiceIsSelectedProvider - */ + #[DataProvider('expandedIsEmptyWhenNoRealChoiceIsSelectedProvider')] public function testExpandedIsEmptyWhenNoRealChoiceIsSelected($expected, $submittedData, $multiple, $required, $placeholder) { $options = [ diff --git a/Tests/Extension/Core/Type/ColorTypeTest.php b/Tests/Extension/Core/Type/ColorTypeTest.php index 5cfab193e4..64a6a71eb2 100644 --- a/Tests/Extension/Core/Type/ColorTypeTest.php +++ b/Tests/Extension/Core/Type/ColorTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Extension\Core\Type\ColorType; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormErrorIterator; @@ -19,9 +20,7 @@ final class ColorTypeTest extends BaseTypeTestCase { public const TESTED_TYPE = ColorType::class; - /** - * @dataProvider validationShouldPassProvider - */ + #[DataProvider('validationShouldPassProvider')] public function testValidationShouldPass(bool $html5, ?string $submittedValue) { $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -53,9 +52,7 @@ public static function validationShouldPassProvider(): array ]; } - /** - * @dataProvider validationShouldFailProvider - */ + #[DataProvider('validationShouldFailProvider')] public function testValidationShouldFail(string $expectedValueParameterValue, ?string $submittedValue, bool $trim = true) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Core/Type/CountryTypeTest.php b/Tests/Extension/Core/Type/CountryTypeTest.php index 171a7491bf..362eb39d51 100644 --- a/Tests/Extension/Core/Type/CountryTypeTest.php +++ b/Tests/Extension/Core/Type/CountryTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Extension\Core\Type\CountryType; use Symfony\Component\Intl\Util\IntlTestHelper; @@ -39,9 +40,7 @@ public function testCountriesAreSelectable() $this->assertContainsEquals(new ChoiceView('MY', 'MY', 'Malaysia'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceTranslationLocaleOption() { $choices = $this->factory @@ -74,9 +73,7 @@ public function testAlpha3Option() $this->assertContainsEquals(new ChoiceView('MYS', 'MYS', 'Malaysia'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceTranslationLocaleAndAlpha3Option() { $choices = $this->factory diff --git a/Tests/Extension/Core/Type/CurrencyTypeTest.php b/Tests/Extension/Core/Type/CurrencyTypeTest.php index e5a1403921..8dbdace1a4 100644 --- a/Tests/Extension/Core/Type/CurrencyTypeTest.php +++ b/Tests/Extension/Core/Type/CurrencyTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Extension\Core\Type\CurrencyType; use Symfony\Component\Intl\Util\IntlTestHelper; @@ -36,9 +37,7 @@ public function testCurrenciesAreSelectable() $this->assertContainsEquals(new ChoiceView('SIT', 'SIT', 'Slovenian Tolar'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceTranslationLocaleOption() { $choices = $this->factory diff --git a/Tests/Extension/Core/Type/DateIntervalTypeTest.php b/Tests/Extension/Core/Type/DateIntervalTypeTest.php index 58e242234d..006676c397 100644 --- a/Tests/Extension/Core/Type/DateIntervalTypeTest.php +++ b/Tests/Extension/Core/Type/DateIntervalTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Extension\Core\Type\DateIntervalType; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; @@ -424,9 +425,7 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = [], $expectedDat $this->assertSame($expectedData, $form->getData()); } - /** - * @dataProvider provideEmptyData - */ + #[DataProvider('provideEmptyData')] public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index 5067bb05e7..d205612771 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; +use Symfony\Component\Clock\DatePoint; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\Type\DateTimeType; use Symfony\Component\Form\FormError; @@ -62,6 +64,37 @@ public function testSubmitDateTime() $this->assertEquals($dateTime, $form->getData()); } + public function testSubmitDatePoint() + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'date_widget' => 'choice', + 'years' => [2010], + 'time_widget' => 'choice', + 'input' => 'date_point', + ]); + + $input = [ + 'date' => [ + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ], + 'time' => [ + 'hour' => '3', + 'minute' => '4', + ], + ]; + + $form->submit($input); + + $this->assertInstanceOf(DatePoint::class, $form->getData()); + $datePoint = DatePoint::createFromMutable(new \DateTime('2010-06-02 03:04:00 UTC')); + $this->assertEquals($datePoint, $form->getData()); + $this->assertEquals($input, $form->getViewData()); + } + public function testSubmitDateTimeImmutable() { $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -701,9 +734,7 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = [], $expectedDat $this->assertSame($expectedData, $form->getData()); } - /** - * @dataProvider provideEmptyData - */ + #[DataProvider('provideEmptyData')] public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 5b9d9d0410..562c4ed1d8 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; +use Symfony\Component\Clock\DatePoint; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\Type\DateType; @@ -115,6 +117,23 @@ public function testSubmitFromSingleTextDateTime() $this->assertEquals('02.06.2010', $form->getViewData()); } + public function testSubmitFromSingleTextDatePoint() + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'html5' => false, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'single_text', + 'input' => 'date_point', + ]); + + $form->submit('2010-06-02'); + + $this->assertInstanceOf(DatePoint::class, $form->getData()); + $this->assertEquals(DatePoint::createFromMutable(new \DateTime('2010-06-02 UTC')), $form->getData()); + $this->assertEquals('2010-06-02', $form->getViewData()); + } + public function testSubmitFromSingleTextDateTimeImmutable() { // we test against "de_DE", so we need the full implementation @@ -396,9 +415,7 @@ public function testSubmitFromInputRawDifferentPattern() $this->assertEquals('06*2010*02', $form->getViewData()); } - /** - * @dataProvider provideDateFormats - */ + #[DataProvider('provideDateFormats')] public function testDatePatternWithFormatOption($format, $pattern) { $view = $this->factory->create(static::TESTED_TYPE, null, [ @@ -955,9 +972,7 @@ public static function provideCompoundWidgets() ]; } - /** - * @dataProvider provideCompoundWidgets - */ + #[DataProvider('provideCompoundWidgets')] public function testYearErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); @@ -970,9 +985,7 @@ public function testYearErrorsBubbleUp($widget) $this->assertSame([$error], iterator_to_array($form->getErrors())); } - /** - * @dataProvider provideCompoundWidgets - */ + #[DataProvider('provideCompoundWidgets')] public function testMonthErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); @@ -985,9 +998,7 @@ public function testMonthErrorsBubbleUp($widget) $this->assertSame([$error], iterator_to_array($form->getErrors())); } - /** - * @dataProvider provideCompoundWidgets - */ + #[DataProvider('provideCompoundWidgets')] public function testDayErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); @@ -1086,9 +1097,7 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = [], $expectedDat $this->assertSame($expectedData, $form->getData()); } - /** - * @dataProvider provideEmptyData - */ + #[DataProvider('provideEmptyData')] public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Core/Type/EnumTypeTest.php b/Tests/Extension/Core/Type/EnumTypeTest.php index 0458720691..1c2be34769 100644 --- a/Tests/Extension/Core/Type/EnumTypeTest.php +++ b/Tests/Extension/Core/Type/EnumTypeTest.php @@ -11,6 +11,7 @@ namespace Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Extension\Core\Type\EnumType; use Symfony\Component\Form\Tests\Extension\Core\Type\BaseTypeTestCase; use Symfony\Component\Form\Tests\Fixtures\Answer; @@ -48,9 +49,7 @@ public function testInvalidClassOptionType() ]); } - /** - * @dataProvider provideSingleSubmitData - */ + #[DataProvider('provideSingleSubmitData')] public function testSubmitSingleNonExpanded(string $class, string $submittedData, \UnitEnum $expectedData) { $form = $this->factory->create($this->getTestedType(), null, [ @@ -66,9 +65,7 @@ public function testSubmitSingleNonExpanded(string $class, string $submittedData $this->assertTrue($form->isSynchronized()); } - /** - * @dataProvider provideSingleSubmitData - */ + #[DataProvider('provideSingleSubmitData')] public function testSubmitSingleExpanded(string $class, string $submittedData, \UnitEnum $expectedData) { $form = $this->factory->create($this->getTestedType(), null, [ @@ -190,9 +187,7 @@ public function testSubmitMultipleChoiceExpandedWithEmptyData() $this->assertSame([Suit::Spades], $form->getData()); } - /** - * @dataProvider provideMultiSubmitData - */ + #[DataProvider('provideMultiSubmitData')] public function testSubmitMultipleNonExpanded(string $class, array $submittedValues, array $expectedValues) { $form = $this->factory->create($this->getTestedType(), null, [ @@ -208,9 +203,7 @@ public function testSubmitMultipleNonExpanded(string $class, array $submittedVal $this->assertTrue($form->isSynchronized()); } - /** - * @dataProvider provideMultiSubmitData - */ + #[DataProvider('provideMultiSubmitData')] public function testSubmitMultipleExpanded(string $class, array $submittedValues, array $expectedValues) { $form = $this->factory->create($this->getTestedType(), null, [ diff --git a/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php b/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php index 122ff44b5d..b449be41cd 100644 --- a/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Forms; use Symfony\Component\Form\Tests\Fixtures\ChoiceTypeExtension; @@ -18,9 +19,7 @@ class ExtendedChoiceTypeTest extends TestCase { - /** - * @dataProvider provideTestedTypes - */ + #[DataProvider('provideTestedTypes')] public function testChoicesAreOverridden($type) { ChoiceTypeExtension::$extendedType = $type; @@ -38,9 +37,7 @@ public function testChoicesAreOverridden($type) $this->assertSame('b', $choices[1]->value); } - /** - * @dataProvider provideTestedTypes - */ + #[DataProvider('provideTestedTypes')] public function testChoiceLoaderIsOverridden($type) { LazyChoiceTypeExtension::$extendedType = $type; diff --git a/Tests/Extension/Core/Type/FileTypeTest.php b/Tests/Extension/Core/Type/FileTypeTest.php index 85907b6959..55cf4cda36 100644 --- a/Tests/Extension/Core/Type/FileTypeTest.php +++ b/Tests/Extension/Core/Type/FileTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Extension\Core\CoreExtension; use Symfony\Component\Form\Extension\Core\Type\FileType; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; @@ -41,9 +42,7 @@ public function testSetData() $this->assertSame($data, $form->getData()); } - /** - * @dataProvider requestHandlerProvider - */ + #[DataProvider('requestHandlerProvider')] public function testSubmit(RequestHandlerInterface $requestHandler) { $form = $this->factory->createBuilder(static::TESTED_TYPE)->setRequestHandler($requestHandler)->getForm(); @@ -54,9 +53,7 @@ public function testSubmit(RequestHandlerInterface $requestHandler) $this->assertSame($data, $form->getData()); } - /** - * @dataProvider requestHandlerProvider - */ + #[DataProvider('requestHandlerProvider')] public function testSetDataMultiple(RequestHandlerInterface $requestHandler) { $form = $this->factory->createBuilder(static::TESTED_TYPE, null, [ @@ -72,9 +69,7 @@ public function testSetDataMultiple(RequestHandlerInterface $requestHandler) $this->assertSame($data, $form->getData()); } - /** - * @dataProvider requestHandlerProvider - */ + #[DataProvider('requestHandlerProvider')] public function testSubmitMultiple(RequestHandlerInterface $requestHandler) { $form = $this->factory->createBuilder(static::TESTED_TYPE, null, [ @@ -94,9 +89,7 @@ public function testSubmitMultiple(RequestHandlerInterface $requestHandler) $this->assertArrayHasKey('multiple', $view->vars['attr']); } - /** - * @dataProvider requestHandlerProvider - */ + #[DataProvider('requestHandlerProvider')] public function testDontPassValueToView(RequestHandlerInterface $requestHandler) { $form = $this->factory->createBuilder(static::TESTED_TYPE)->setRequestHandler($requestHandler)->getForm(); @@ -133,9 +126,7 @@ public function testSubmitNullWhenMultiple() $this->assertSame([], $form->getViewData()); } - /** - * @dataProvider requestHandlerProvider - */ + #[DataProvider('requestHandlerProvider')] public function testSubmittedFilePathsAreDropped(RequestHandlerInterface $requestHandler) { $form = $this->factory->createBuilder(static::TESTED_TYPE)->setRequestHandler($requestHandler)->getForm(); @@ -146,9 +137,7 @@ public function testSubmittedFilePathsAreDropped(RequestHandlerInterface $reques $this->assertSame('', $form->getViewData()); } - /** - * @dataProvider requestHandlerProvider - */ + #[DataProvider('requestHandlerProvider')] public function testMultipleSubmittedFilePathsAreDropped(RequestHandlerInterface $requestHandler) { $form = $this->factory @@ -166,9 +155,7 @@ public function testMultipleSubmittedFilePathsAreDropped(RequestHandlerInterface $this->assertCount(1, $form->getData()); } - /** - * @dataProvider requestHandlerProvider - */ + #[DataProvider('requestHandlerProvider')] public function testSubmitNonArrayValueWhenMultiple(RequestHandlerInterface $requestHandler) { $form = $this->factory @@ -192,9 +179,7 @@ public static function requestHandlerProvider(): array ]; } - /** - * @dataProvider uploadFileErrorCodes - */ + #[DataProvider('uploadFileErrorCodes')] public function testFailedFileUploadIsTurnedIntoFormErrorUsingHttpFoundationRequestHandler($errorCode, $expectedErrorMessage) { $requestHandler = new HttpFoundationRequestHandler(); @@ -212,9 +197,7 @@ public function testFailedFileUploadIsTurnedIntoFormErrorUsingHttpFoundationRequ } } - /** - * @dataProvider uploadFileErrorCodes - */ + #[DataProvider('uploadFileErrorCodes')] public function testFailedFileUploadIsTurnedIntoFormErrorUsingNativeRequestHandler($errorCode, $expectedErrorMessage) { $form = $this->factory @@ -237,9 +220,7 @@ public function testFailedFileUploadIsTurnedIntoFormErrorUsingNativeRequestHandl } } - /** - * @dataProvider uploadFileErrorCodes - */ + #[DataProvider('uploadFileErrorCodes')] public function testMultipleSubmittedFailedFileUploadsAreTurnedIntoFormErrorUsingHttpFoundationRequestHandler($errorCode, $expectedErrorMessage) { $requestHandler = new HttpFoundationRequestHandler(); @@ -264,9 +245,7 @@ public function testMultipleSubmittedFailedFileUploadsAreTurnedIntoFormErrorUsin } } - /** - * @dataProvider uploadFileErrorCodes - */ + #[DataProvider('uploadFileErrorCodes')] public function testMultipleSubmittedFailedFileUploadsAreTurnedIntoFormErrorUsingNativeRequestHandler($errorCode, $expectedErrorMessage) { $form = $this->factory diff --git a/Tests/Extension/Core/Type/IntegerTypeTest.php b/Tests/Extension/Core/Type/IntegerTypeTest.php index 9a689d58f8..65a695f420 100644 --- a/Tests/Extension/Core/Type/IntegerTypeTest.php +++ b/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Intl\Util\IntlTestHelper; @@ -29,12 +30,12 @@ protected function setUp(): void protected function tearDown(): void { - \Locale::setDefault($this->previousLocale); + if (isset($this->defaultLocale)) { + \Locale::setDefault($this->defaultLocale); + } } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testArabicLocale() { \Locale::setDefault('ar'); @@ -46,9 +47,7 @@ public function testArabicLocale() $this->assertSame('123456', $form->getViewData()); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testArabicLocaleNonHtml5() { \Locale::setDefault('ar'); diff --git a/Tests/Extension/Core/Type/LanguageTypeTest.php b/Tests/Extension/Core/Type/LanguageTypeTest.php index 50bd373a0f..1c1570e369 100644 --- a/Tests/Extension/Core/Type/LanguageTypeTest.php +++ b/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\Type\LanguageType; @@ -37,9 +38,7 @@ public function testCountriesAreSelectable() $this->assertContainsEquals(new ChoiceView('my', 'my', 'Burmese'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceTranslationLocaleOption() { $choices = $this->factory @@ -69,9 +68,7 @@ public function testAlpha3Option() $this->assertNotContainsEquals(new ChoiceView('my', 'my', 'Burmese'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceTranslationLocaleAndAlpha3Option() { $choices = $this->factory @@ -88,9 +85,7 @@ public function testChoiceTranslationLocaleAndAlpha3Option() $this->assertNotContainsEquals(new ChoiceView('my', 'my', 'бірманська'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceSelfTranslationOption() { $choices = $this->factory @@ -108,9 +103,7 @@ public function testChoiceSelfTranslationOption() $this->assertContainsEquals(new ChoiceView('zh', 'zh', '中文'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceSelfTranslationAndAlpha3Options() { $choices = $this->factory diff --git a/Tests/Extension/Core/Type/LocaleTypeTest.php b/Tests/Extension/Core/Type/LocaleTypeTest.php index 381cc55bec..97dbe0b2f1 100644 --- a/Tests/Extension/Core/Type/LocaleTypeTest.php +++ b/Tests/Extension/Core/Type/LocaleTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Extension\Core\Type\LocaleType; use Symfony\Component\Intl\Util\IntlTestHelper; @@ -36,9 +37,7 @@ public function testLocalesAreSelectable() $this->assertContainsEquals(new ChoiceView('zh_Hant_HK', 'zh_Hant_HK', 'Chinese (Traditional, Hong Kong SAR China)'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceTranslationLocaleOption() { $choices = $this->factory diff --git a/Tests/Extension/Core/Type/MoneyTypeTest.php b/Tests/Extension/Core/Type/MoneyTypeTest.php index 41d75346a4..88d7eb54a9 100644 --- a/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -34,7 +34,9 @@ protected function setUp(): void protected function tearDown(): void { - \Locale::setDefault($this->defaultLocale); + if (isset($this->defaultLocale)) { + \Locale::setDefault($this->defaultLocale); + } } public function testPassMoneyPatternToView() diff --git a/Tests/Extension/Core/Type/NumberTypeTest.php b/Tests/Extension/Core/Type/NumberTypeTest.php index 172096422f..45f9192f1d 100644 --- a/Tests/Extension/Core/Type/NumberTypeTest.php +++ b/Tests/Extension/Core/Type/NumberTypeTest.php @@ -35,7 +35,9 @@ protected function setUp(): void protected function tearDown(): void { - \Locale::setDefault($this->defaultLocale); + if (isset($this->defaultLocale)) { + \Locale::setDefault($this->defaultLocale); + } } public function testDefaultFormatting() diff --git a/Tests/Extension/Core/Type/PercentTypeTest.php b/Tests/Extension/Core/Type/PercentTypeTest.php index 90d02f8f19..909afb6fd4 100644 --- a/Tests/Extension/Core/Type/PercentTypeTest.php +++ b/Tests/Extension/Core/Type/PercentTypeTest.php @@ -34,7 +34,9 @@ protected function setUp(): void protected function tearDown(): void { - \Locale::setDefault($this->defaultLocale); + if (isset($this->defaultLocale)) { + \Locale::setDefault($this->defaultLocale); + } } public function testSubmitWithRoundingMode() diff --git a/Tests/Extension/Core/Type/RepeatedTypeTest.php b/Tests/Extension/Core/Type/RepeatedTypeTest.php index 2d19a0613d..1bdfe52f75 100644 --- a/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Extension\Core\Type\RepeatedType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Form; @@ -92,9 +93,7 @@ public function testMappedOverridesDefault() $this->assertTrue($form['second']->getConfig()->getMapped()); } - /** - * @dataProvider notMappedConfigurationKeys - */ + #[DataProvider('notMappedConfigurationKeys')] public function testNotMappedInnerIsOverridden($configurationKey) { $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -190,9 +189,7 @@ public function testSetOptionsPerChildAndOverwrite() $this->assertTrue($form['second']->isRequired()); } - /** - * @dataProvider emptyDataProvider - */ + #[DataProvider('emptyDataProvider')] public function testSubmitNullForTextTypeWithEmptyDataOptionSetToEmptyString($emptyData, $submittedData, $expected) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Core/Type/TextTypeTest.php b/Tests/Extension/Core/Type/TextTypeTest.php index 4832151684..043b69b581 100644 --- a/Tests/Extension/Core/Type/TextTypeTest.php +++ b/Tests/Extension/Core/Type/TextTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Extension\Core\Type\TextType; class TextTypeTest extends BaseTypeTestCase @@ -44,10 +45,9 @@ public static function provideZeros(): array } /** - * @dataProvider provideZeros - * * @see https://github.com/symfony/symfony/issues/1986 */ + #[DataProvider('provideZeros')] public function testSetDataThroughParamsWithZero($data, $dataAsString) { $form = $this->factory->create(static::TESTED_TYPE, null, array_merge($this->getTestOptions(), [ diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 8a2baf1b4c..2a36c05f71 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; +use Symfony\Component\Clock\DatePoint; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Exception\LogicException; @@ -45,6 +47,28 @@ public function testSubmitDateTime() $this->assertEquals($input, $form->getViewData()); } + public function testSubmitDatePoint() + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + 'widget' => 'choice', + 'input' => 'date_point', + ]); + + $input = [ + 'hour' => '3', + 'minute' => '4', + ]; + + $form->submit($input); + + $this->assertInstanceOf(DatePoint::class, $form->getData()); + $datePoint = DatePoint::createFromMutable(new \DateTime('1970-01-01 03:04:00 UTC')); + $this->assertEquals($datePoint, $form->getData()); + $this->assertEquals($input, $form->getViewData()); + } + public function testSubmitDateTimeImmutable() { $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -907,9 +931,7 @@ public static function provideCompoundWidgets() ]; } - /** - * @dataProvider provideCompoundWidgets - */ + #[DataProvider('provideCompoundWidgets')] public function testHourErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); @@ -922,9 +944,7 @@ public function testHourErrorsBubbleUp($widget) $this->assertSame([$error], iterator_to_array($form->getErrors())); } - /** - * @dataProvider provideCompoundWidgets - */ + #[DataProvider('provideCompoundWidgets')] public function testMinuteErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); @@ -937,9 +957,7 @@ public function testMinuteErrorsBubbleUp($widget) $this->assertSame([$error], iterator_to_array($form->getErrors())); } - /** - * @dataProvider provideCompoundWidgets - */ + #[DataProvider('provideCompoundWidgets')] public function testSecondErrorsBubbleUp($widget) { $error = new FormError('Invalid!'); @@ -1128,9 +1146,7 @@ public function testArrayTimeWithReferenceDoesUseReferenceDateOnModelTransform() ], $form->getViewData()); } - /** - * @dataProvider provideEmptyData - */ + #[DataProvider('provideEmptyData')] public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Core/Type/TimezoneTypeTest.php b/Tests/Extension/Core/Type/TimezoneTypeTest.php index 1c37229be1..2675156003 100644 --- a/Tests/Extension/Core/Type/TimezoneTypeTest.php +++ b/Tests/Extension/Core/Type/TimezoneTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\RequiresPhpExtension; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\Type\TimezoneType; @@ -74,9 +75,7 @@ public function testDateTimeZoneInputWithBc() $this->assertContainsEquals('Europe/Saratov', $form->getConfig()->getAttribute('choice_list')->getValues()); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testIntlTimeZoneInput() { $form = $this->factory->create(static::TESTED_TYPE, \IntlTimeZone::createTimeZone('America/New_York'), ['input' => 'intltimezone']); @@ -96,9 +95,7 @@ public function testIntlTimeZoneInput() $this->assertEquals([\IntlTimeZone::createTimeZone('Europe/Amsterdam'), \IntlTimeZone::createTimeZone('Europe/Paris')], $form->getData()); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testIntlTimeZoneInputWithBc() { $reflector = new \ReflectionExtension('intl'); @@ -119,9 +116,7 @@ public function testIntlTimeZoneInputWithBc() $this->assertNotContains('Europe/Saratov', $form->getConfig()->getAttribute('choice_list')->getValues()); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testIntlTimeZoneInputWithBcAndIntl() { $reflector = new \ReflectionExtension('intl'); @@ -153,9 +148,7 @@ public function testTimezonesAreSelectableWithIntl() $this->assertContainsEquals(new ChoiceView('Etc/UTC', 'Etc/UTC', 'Coordinated Universal Time'), $choices); } - /** - * @requires extension intl - */ + #[RequiresPhpExtension('intl')] public function testChoiceTranslationLocaleOptionWithIntl() { $choices = $this->factory diff --git a/Tests/Extension/Core/Type/UrlTypeTest.php b/Tests/Extension/Core/Type/UrlTypeTest.php index a0d335647d..714e92f095 100644 --- a/Tests/Extension/Core/Type/UrlTypeTest.php +++ b/Tests/Extension/Core/Type/UrlTypeTest.php @@ -11,30 +11,13 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait; use Symfony\Component\Form\Extension\Core\Type\UrlType; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; class UrlTypeTest extends TextTypeTest { - use ExpectUserDeprecationMessageTrait; - public const TESTED_TYPE = UrlType::class; - /** - * @group legacy - */ - public function testSubmitAddsDefaultProtocolIfNoneIsIncluded() - { - $this->expectUserDeprecationMessage('Since symfony/form 7.1: Not configuring the "default_protocol" option when using the UrlType is deprecated. It will default to "null" in 8.0.'); - $form = $this->factory->create(static::TESTED_TYPE, 'name'); - - $form->submit('www.domain.com'); - - $this->assertSame('http://www.domain.com', $form->getData()); - $this->assertSame('http://www.domain.com', $form->getViewData()); - } - public function testSubmitAddsNoDefaultProtocolIfAlreadyIncluded() { $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -107,6 +90,6 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expect protected function getTestOptions(): array { - return ['default_protocol' => 'http']; + return []; } } diff --git a/Tests/Extension/Core/Type/WeekTypeTest.php b/Tests/Extension/Core/Type/WeekTypeTest.php index b4d58fd95c..df0ec8fc7b 100644 --- a/Tests/Extension/Core/Type/WeekTypeTest.php +++ b/Tests/Extension/Core/Type/WeekTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use PHPUnit\Framework\Attributes\DataProvider; use Symfony\Component\Form\Extension\Core\Type\WeekType; use Symfony\Component\Form\FormError; @@ -300,9 +301,7 @@ public function testSubmitNullUsesDefaultEmptyData($emptyData = [], $expectedDat $this->assertSame(['year' => null, 'week' => null], $form->getData()); } - /** - * @dataProvider provideEmptyData - */ + #[DataProvider('provideEmptyData')] public function testSubmitNullUsesDateEmptyDataString($widget, $emptyData, $expectedData) { $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index d5bce6527b..3bbfa29209 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\Type; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; @@ -166,9 +167,7 @@ public static function provideBoolean() ]; } - /** - * @dataProvider provideBoolean - */ + #[DataProvider('provideBoolean')] public function testValidateTokenOnSubmitIfRootAndCompound($valid) { $this->tokenManager->expects($this->once()) @@ -198,9 +197,7 @@ public function testValidateTokenOnSubmitIfRootAndCompound($valid) $this->assertSame($valid, $form->isValid()); } - /** - * @dataProvider provideBoolean - */ + #[DataProvider('provideBoolean')] public function testValidateTokenOnSubmitIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid) { $this->tokenManager->expects($this->once()) @@ -229,9 +226,7 @@ public function testValidateTokenOnSubmitIfRootAndCompoundUsesFormNameAsIntentio $this->assertSame($valid, $form->isValid()); } - /** - * @dataProvider provideBoolean - */ + #[DataProvider('provideBoolean')] public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid) { $this->tokenManager->expects($this->once()) diff --git a/Tests/Extension/PasswordHasher/Type/PasswordTypePasswordHasherExtensionTest.php b/Tests/Extension/PasswordHasher/Type/PasswordTypePasswordHasherExtensionTest.php index 07d1292a3f..e46bf82f39 100644 --- a/Tests/Extension/PasswordHasher/Type/PasswordTypePasswordHasherExtensionTest.php +++ b/Tests/Extension/PasswordHasher/Type/PasswordTypePasswordHasherExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\PasswordHasher\Type; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Extension\Core\Type\FormType; @@ -144,9 +145,7 @@ public function testPasswordHashSuccessWithEmptyData() $this->assertSame($user->getPassword(), $hashedPassword); } - /** - * @dataProvider provideRepeatedPasswordField - */ + #[DataProvider('provideRepeatedPasswordField')] public function testRepeatedPasswordField(string $type, array $options = []) { $user = new User(); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php index b0c7d719ae..1388fb480a 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; +use PHPUnit\Framework\Attributes\Group; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; use Symfony\Component\Form\Test\FormPerformanceTestCase; use Symfony\Component\Validator\Validation; @@ -29,9 +30,8 @@ protected function getExtensions(): array /** * findClickedButton() used to have an exponential number of calls. - * - * @group benchmark */ + #[Group('benchmark')] public function testValidationPerformance() { $this->setMaxRunningTime(1); diff --git a/Tests/Extension/Validator/Type/UrlTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/UrlTypeValidatorExtensionTest.php index edb212cbd4..e6314a3c59 100644 --- a/Tests/Extension/Validator/Type/UrlTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/UrlTypeValidatorExtensionTest.php @@ -20,7 +20,7 @@ class UrlTypeValidatorExtensionTest extends BaseValidatorExtensionTestCase protected function createForm(array $options = []) { - return $this->factory->create(UrlType::class, null, $options + ['default_protocol' => 'http']); + return $this->factory->create(UrlType::class, null, $options); } public function testInvalidMessage() diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index 1d0e0f872d..a915e861bb 100644 --- a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\CollectionType; @@ -60,9 +61,7 @@ protected function setUp(): void $this->guesser = new ValidatorTypeGuesser($this->metadataFactory); } - /** - * @dataProvider guessTypeProvider - */ + #[DataProvider('guessTypeProvider')] public function testGuessType(Constraint $constraint, TypeGuess $guess) { $this->metadata->addPropertyConstraint(self::TEST_PROPERTY, $constraint); @@ -101,9 +100,7 @@ public static function guessRequiredProvider() ]; } - /** - * @dataProvider guessRequiredProvider - */ + #[DataProvider('guessRequiredProvider')] public function testGuessRequired($constraint, $guess) { // add distracting constraint @@ -185,9 +182,7 @@ public static function maxLengthTypeProvider() ]; } - /** - * @dataProvider maxLengthTypeProvider - */ + #[DataProvider('maxLengthTypeProvider')] public function testGuessMaxLengthForConstraintWithType($type) { $constraint = new Type($type); diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 0aeb35adcc..386fde2628 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\CallbackTransformer; @@ -786,9 +787,7 @@ public static function provideDefaultTests() ]; } - /** - * @dataProvider provideDefaultTests - */ + #[DataProvider('provideDefaultTests')] public function testDefaultErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); @@ -1241,9 +1240,7 @@ public static function provideCustomDataErrorTests() ]; } - /** - * @dataProvider provideCustomDataErrorTests - */ + #[DataProvider('provideCustomDataErrorTests')] public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); @@ -1441,9 +1438,7 @@ public static function provideCustomFormErrorTests() ]; } - /** - * @dataProvider provideCustomFormErrorTests - */ + #[DataProvider('provideCustomFormErrorTests')] public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName, $errorPath, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); @@ -1508,9 +1503,7 @@ public static function provideErrorTestsForFormInheritingParentData() ]; } - /** - * @dataProvider provideErrorTestsForFormInheritingParentData - */ + #[DataProvider('provideErrorTestsForFormInheritingParentData')] public function testErrorMappingForFormInheritingParentData($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php index ebae56eb42..09c71d8de4 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\ViolationMapper; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPath; @@ -84,9 +85,7 @@ public static function providePaths() ]; } - /** - * @dataProvider providePaths - */ + #[DataProvider('providePaths')] public function testCreatePath($string, $entries, $slicedPath = null) { $slicedPath ??= $string; @@ -120,9 +119,7 @@ public static function provideParents() ]; } - /** - * @dataProvider provideParents - */ + #[DataProvider('provideParents')] public function testGetParent($violationPath, $parentPath) { $path = new ViolationPath($violationPath); diff --git a/Tests/Fixtures/AlternatingRowType.php b/Tests/Fixtures/AlternatingRowType.php index 3e0bb40c2b..9d80f3e13c 100644 --- a/Tests/Fixtures/AlternatingRowType.php +++ b/Tests/Fixtures/AlternatingRowType.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; diff --git a/Tests/Fixtures/ArrayChoiceLoader.php b/Tests/Fixtures/ArrayChoiceLoader.php index 8c5a3a4733..c5e137ec26 100644 --- a/Tests/Fixtures/ArrayChoiceLoader.php +++ b/Tests/Fixtures/ArrayChoiceLoader.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; diff --git a/Tests/Fixtures/AuthorType.php b/Tests/Fixtures/AuthorType.php index a55dbfeacc..df49e0d7a7 100644 --- a/Tests/Fixtures/AuthorType.php +++ b/Tests/Fixtures/AuthorType.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; diff --git a/Tests/Fixtures/EnumFormTypeGuesserCase.php b/Tests/Fixtures/EnumFormTypeGuesserCase.php new file mode 100644 index 0000000000..3028ec8c84 --- /dev/null +++ b/Tests/Fixtures/EnumFormTypeGuesserCase.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\Form\Tests\Fixtures; + +class EnumFormTypeGuesserCase +{ + public string $string; + public UndefinedEnum $undefinedEnum; + public EnumFormTypeGuesserCaseEnum $enum; + public ?EnumFormTypeGuesserCaseEnum $nullableEnum; + public BackedEnumFormTypeGuesserCaseEnum $backedEnum; + public ?BackedEnumFormTypeGuesserCaseEnum $nullableBackedEnum; + public EnumFormTypeGuesserCaseEnum|BackedEnumFormTypeGuesserCaseEnum $enumUnion; + public EnumFormTypeGuesserCaseEnum&BackedEnumFormTypeGuesserCaseEnum $enumIntersection; +} + +enum EnumFormTypeGuesserCaseEnum +{ + case Foo; + case Bar; +} + +enum BackedEnumFormTypeGuesserCaseEnum: string +{ + case Foo = 'foo'; + case Bar = 'bar'; +} diff --git a/Tests/Fixtures/FixedDataTransformer.php b/Tests/Fixtures/FixedDataTransformer.php index f3121fc103..2b910ea99b 100644 --- a/Tests/Fixtures/FixedDataTransformer.php +++ b/Tests/Fixtures/FixedDataTransformer.php @@ -26,7 +26,7 @@ public function __construct(array $mapping) public function transform($value): mixed { if (!\array_key_exists($value, $this->mapping)) { - throw new TransformationFailedException(sprintf('No mapping for value "%s"', $value)); + throw new TransformationFailedException(\sprintf('No mapping for value "%s"', $value)); } return $this->mapping[$value]; @@ -37,7 +37,7 @@ public function reverseTransform($value): mixed $result = array_search($value, $this->mapping, true); if (false === $result) { - throw new TransformationFailedException(sprintf('No reverse mapping for value "%s"', $value)); + throw new TransformationFailedException(\sprintf('No reverse mapping for value "%s"', $value)); } return $result; diff --git a/Tests/Fixtures/Organization.php b/Tests/Fixtures/Organization.php index db9cee9f96..f50c732e10 100644 --- a/Tests/Fixtures/Organization.php +++ b/Tests/Fixtures/Organization.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Form\Tests\Fixtures; class Organization @@ -19,6 +28,7 @@ public function getAuthors(): array public function addAuthor(Author $author): self { $this->authors[] = $author; + return $this; } @@ -27,6 +37,7 @@ public function removeAuthor(Author $author): self if (false !== $key = array_search($author, $this->authors, true)) { array_splice($this->authors, $key, 1); } + return $this; } } diff --git a/Tests/FormConfigTest.php b/Tests/FormConfigTest.php index 6de3e9416f..192ba5c30c 100644 --- a/Tests/FormConfigTest.php +++ b/Tests/FormConfigTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\FormConfigBuilder; @@ -62,9 +63,7 @@ public static function getHtml4Ids() ]; } - /** - * @dataProvider getHtml4Ids - */ + #[DataProvider('getHtml4Ids')] public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $expectedException = null) { if (null !== $expectedException) { diff --git a/Tests/FormErrorIteratorTest.php b/Tests/FormErrorIteratorTest.php index 56472c82e9..97a7ccd064 100644 --- a/Tests/FormErrorIteratorTest.php +++ b/Tests/FormErrorIteratorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\FormBuilder; @@ -23,9 +24,7 @@ class FormErrorIteratorTest extends TestCase { - /** - * @dataProvider findByCodesProvider - */ + #[DataProvider('findByCodesProvider')] public function testFindByCodes($code, $violationsCount) { $formBuilder = new FormBuilder( diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index fa28f75472..13a1bc2599 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\AbstractType; @@ -151,9 +152,7 @@ public function testGetBlockPrefix() $this->assertSame('configurable_form_prefix', $resolvedType->getBlockPrefix()); } - /** - * @dataProvider provideTypeClassBlockPrefixTuples - */ + #[DataProvider('provideTypeClassBlockPrefixTuples')] public function testBlockPrefixDefaultsToFQCNIfNoName($typeClass, $blockPrefix) { $resolvedType = new ResolvedFormType(new $typeClass()); diff --git a/Tests/Resources/TranslationFilesTest.php b/Tests/Resources/TranslationFilesTest.php index 157335dc6d..ccfb8926b1 100644 --- a/Tests/Resources/TranslationFilesTest.php +++ b/Tests/Resources/TranslationFilesTest.php @@ -11,14 +11,13 @@ namespace Symfony\Component\Form\Tests\Resources; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Translation\Util\XliffUtils; class TranslationFilesTest extends TestCase { - /** - * @dataProvider provideTranslationFiles - */ + #[DataProvider('provideTranslationFiles')] public function testTranslationFileIsValid($filePath) { $document = new \DOMDocument(); @@ -29,9 +28,7 @@ public function testTranslationFileIsValid($filePath) $this->assertCount(0, $errors, \sprintf('"%s" is invalid:%s', $filePath, \PHP_EOL.implode(\PHP_EOL, array_column($errors, 'message')))); } - /** - * @dataProvider provideTranslationFiles - */ + #[DataProvider('provideTranslationFiles')] public function testTranslationFileIsValidWithoutEntityLoader($filePath) { $document = new \DOMDocument(); diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 0f9a6dc41c..01ae6a5a16 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Form\Exception\AlreadySubmittedException; @@ -75,9 +76,7 @@ protected function setUp(): void $this->form = $this->createForm(); } - /** - * @dataProvider provideFormNames - */ + #[DataProvider('provideFormNames')] public function testGetPropertyPath($name, $propertyPath) { $config = new FormConfigBuilder($name, null, new EventDispatcher()); @@ -230,9 +229,7 @@ public function testNotRequired() $this->assertFalse($child->isRequired()); } - /** - * @dataProvider getDisabledStates - */ + #[DataProvider('getDisabledStates')] public function testAlwaysDisabledIfParentDisabled($parentDisabled, $disabled, $result) { $parent = $this->getBuilder()->setDisabled($parentDisabled)->getForm(); @@ -1052,7 +1049,7 @@ public function testInitializeSetsDefaultData() $config = $this->getBuilder()->setData('DEFAULT')->getFormConfig(); $form = new Form($config); - /** @var Form $form */ + /* @var Form $form */ $form->initialize(); $this->assertSame('DEFAULT', $form->getData()); diff --git a/Tests/Util/ServerParamsTest.php b/Tests/Util/ServerParamsTest.php index 1904812d81..778819d37f 100644 --- a/Tests/Util/ServerParamsTest.php +++ b/Tests/Util/ServerParamsTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Util; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Util\ServerParams; use Symfony\Component\HttpFoundation\Request; @@ -40,7 +41,7 @@ public function testGetContentLengthFromRequest() $this->assertEquals(1024, $serverParams->getContentLength()); } - /** @dataProvider getGetPostMaxSizeTestData */ + #[DataProvider('getGetPostMaxSizeTestData')] public function testGetPostMaxSize($size, $bytes) { $serverParams = new DummyServerParams($size); diff --git a/Tests/Util/StringUtilTest.php b/Tests/Util/StringUtilTest.php index d51481f6c1..a7221e55f6 100644 --- a/Tests/Util/StringUtilTest.php +++ b/Tests/Util/StringUtilTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Util; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Symfony\Component\Form\Util\StringUtil; @@ -24,17 +25,13 @@ public static function trimProvider(): array ]; } - /** - * @dataProvider trimProvider - */ + #[DataProvider('trimProvider')] public function testTrim($data, $expectedData) { $this->assertSame($expectedData, StringUtil::trim($data)); } - /** - * @dataProvider spaceProvider - */ + #[DataProvider('spaceProvider')] public function testTrimUtf8Separators($hex) { // Convert hexadecimal representation into binary @@ -87,9 +84,7 @@ public static function spaceProvider(): array ]; } - /** - * @dataProvider fqcnToBlockPrefixProvider - */ + #[DataProvider('fqcnToBlockPrefixProvider')] public function testFqcnToBlockPrefix($fqcn, $expectedBlockPrefix) { $blockPrefix = StringUtil::fqcnToBlockPrefix($fqcn); diff --git a/Tests/VersionAwareTestTrait.php b/Tests/VersionAwareTestTrait.php deleted file mode 100644 index 62e98934e3..0000000000 --- a/Tests/VersionAwareTestTrait.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests; - -/** - * @deprecated since Symfony 7.2, use feature detection instead. - */ -trait VersionAwareTestTrait -{ - protected static int $supportedFeatureSetVersion = 404; - - /** - * @deprecated since Symfony 7.2, use feature detection instead. - */ - protected function requiresFeatureSet(int $requiredFeatureSetVersion) - { - trigger_deprecation('symfony/form', '7.2', 'The "%s" trait is deprecated, use feature detection instead.', VersionAwareTestTrait::class); - - if ($requiredFeatureSetVersion > static::$supportedFeatureSetVersion) { - $this->markTestSkipped(\sprintf('Test requires features from symfony/form %.2f but only version %.2f is supported.', $requiredFeatureSetVersion / 100, static::$supportedFeatureSetVersion / 100)); - } - } -} diff --git a/Util/OrderedHashMapIterator.php b/Util/OrderedHashMapIterator.php index 927a28c04a..ed4ee0b84f 100644 --- a/Util/OrderedHashMapIterator.php +++ b/Util/OrderedHashMapIterator.php @@ -51,12 +51,12 @@ public function __construct( $this->managedCursors[$this->cursorId] = &$this->cursor; } - public function __sleep(): array + public function __serialize(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } - public function __wakeup(): void + public function __unserialize(array $data): void { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } diff --git a/composer.json b/composer.json index f4403ba74d..491e7a4e77 100644 --- a/composer.json +++ b/composer.json @@ -16,43 +16,36 @@ } ], "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/options-resolver": "^7.3", - "symfony/polyfill-ctype": "~1.8", + "php": ">=8.4", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/options-resolver": "^7.4|^8.0", + "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-intl-icu": "^1.21", - "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "^6.4|^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/property-access": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3" }, "require-dev": { "doctrine/collections": "^1.0|^2.0", - "symfony/validator": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/html-sanitizer": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/security-csrf": "^6.4|^7.0", - "symfony/translation": "^6.4.3|^7.0.3", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0" + "symfony/clock": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/html-sanitizer": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", + "symfony/security-core": "^7.4|^8.0", + "symfony/security-csrf": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "conflict": { - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", - "symfony/error-handler": "<6.4", - "symfony/framework-bundle": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/translation": "<6.4.3|>=7.0,<7.0.3", "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4" + "symfony/validator": "<7.4" }, "autoload": { "psr-4": { "Symfony\\Component\\Form\\": "" }, diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 148f8f58dd..b4d5784151 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,11 @@ @@ -18,7 +19,7 @@ - + ./ @@ -27,5 +28,9 @@ ./Tests ./vendor - + + + + +