diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b1fabfd1..00d3b2fc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +7.3 +--- + + * Add support for displaying nested options in DebugCommand + * Add support for strings as data for the `MoneyType` + 7.2 --- diff --git a/Console/Descriptor/Descriptor.php b/Console/Descriptor/Descriptor.php index c910acdf4..91778f819 100644 --- a/Console/Descriptor/Descriptor.php +++ b/Console/Descriptor/Descriptor.php @@ -118,6 +118,7 @@ protected function getOptionDefinition(OptionsResolver $optionsResolver, string 'allowedValues' => 'getAllowedValues', 'normalizers' => 'getNormalizers', 'deprecation' => 'getDeprecation', + 'nestedOptions' => 'getNestedOptions', ]; foreach ($map as $key => $method) { diff --git a/Console/Descriptor/JsonDescriptor.php b/Console/Descriptor/JsonDescriptor.php index 1f5c7bfa5..1eca762b7 100644 --- a/Console/Descriptor/JsonDescriptor.php +++ b/Console/Descriptor/JsonDescriptor.php @@ -62,6 +62,12 @@ protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedF } protected function describeOption(OptionsResolver $optionsResolver, array $options): void + { + $data = $this->getOptionDescription($optionsResolver, $options); + $this->writeData($data, $options); + } + + private function getOptionDescription(OptionsResolver $optionsResolver, array $options): array { $definition = $this->getOptionDefinition($optionsResolver, $options['option']); @@ -90,7 +96,17 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio } $data['has_normalizer'] = isset($definition['normalizers']); - $this->writeData($data, $options); + if ($data['has_nested_options'] = isset($definition['nestedOptions'])) { + $nestedResolver = new OptionsResolver(); + foreach ($definition['nestedOptions'] as $nestedOption) { + $nestedOption($nestedResolver, $optionsResolver); + } + foreach ($nestedResolver->getDefinedOptions() as $option) { + $data['nested_options'][$option] = $this->getOptionDescription($nestedResolver, ['option' => $option]); + } + } + + return $data; } private function writeData(array $data, array $options): void diff --git a/Console/Descriptor/TextDescriptor.php b/Console/Descriptor/TextDescriptor.php index 630b87253..e12b34262 100644 --- a/Console/Descriptor/TextDescriptor.php +++ b/Console/Descriptor/TextDescriptor.php @@ -118,12 +118,19 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio 'Allowed types' => 'allowedTypes', 'Allowed values' => 'allowedValues', 'Normalizers' => 'normalizers', + 'Nested Options' => 'nestedOptions', ]; $rows = []; foreach ($map as $label => $name) { $value = \array_key_exists($name, $definition) ? $dump($definition[$name]) : '-'; if ('default' === $name && isset($definition['lazy'])) { $value = "Value: $value\n\nClosure(s): ".$dump($definition['lazy']); + } elseif ('nestedOptions' === $name && isset($definition['nestedOptions'])) { + $nestedResolver = new OptionsResolver(); + foreach ($definition['nestedOptions'] as $nestedOption) { + $nestedOption($nestedResolver, $optionsResolver); + } + $value = $dump($nestedResolver->getDefinedOptions()); } $rows[] = ["<info>$label</info>", $value]; diff --git a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index b03f8da44..e9c9cb9e5 100644 --- a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -70,7 +70,7 @@ public function reverseTransform(mixed $value): int|float|null if (null !== $value) { $value = (string) ($value * $this->divisor); - if ('float' === $this->input) { + if ('integer' !== $this->input) { return (float) $value; } diff --git a/Extension/Core/Type/MoneyType.php b/Extension/Core/Type/MoneyType.php index 2657b03af..38dbfc038 100644 --- a/Extension/Core/Type/MoneyType.php +++ b/Extension/Core/Type/MoneyType.php @@ -14,6 +14,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; +use Symfony\Component\Form\Extension\Core\DataTransformer\StringToFloatTransformer; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; @@ -38,6 +39,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void $options['input'], )) ; + + if ('string' === $options['input']) { + $builder->addModelTransformer(new StringToFloatTransformer($options['scale'])); + } } public function buildView(FormView $view, FormInterface $form, array $options): void @@ -77,7 +82,7 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedTypes('html5', 'bool'); - $resolver->setAllowedValues('input', ['float', 'integer']); + $resolver->setAllowedValues('input', ['float', 'integer', 'string']); $resolver->setNormalizer('grouping', static function (Options $options, $value) { if ($value && $options['html5']) { diff --git a/Tests/Command/DebugCommandTest.php b/Tests/Command/DebugCommandTest.php index 4537099c2..cac92addb 100644 --- a/Tests/Command/DebugCommandTest.php +++ b/Tests/Command/DebugCommandTest.php @@ -179,6 +179,8 @@ class:%s } %s ] %s ---------------- -----------%s + Nested Options - %s + ---------------- -----------%s TXT , $tester->getDisplay(true)); diff --git a/Tests/Console/Descriptor/AbstractDescriptorTestCase.php b/Tests/Console/Descriptor/AbstractDescriptorTestCase.php index 8a99c205c..456b433ee 100644 --- a/Tests/Console/Descriptor/AbstractDescriptorTestCase.php +++ b/Tests/Console/Descriptor/AbstractDescriptorTestCase.php @@ -130,6 +130,11 @@ public static function getDescribeOptionTestData() $options['option'] = 'bar'; $options['show_deprecated'] = true; yield [$resolvedType->getOptionsResolver(), $options, 'deprecated_option']; + + $resolvedType = new ResolvedFormType(new FooType(), [], $parent); + $options['type'] = $resolvedType->getInnerType(); + $options['option'] = 'baz'; + yield [$resolvedType->getOptionsResolver(), $options, 'nested_option']; } abstract protected function getDescriptor(); @@ -172,5 +177,9 @@ public function configureOptions(OptionsResolver $resolver): void $resolver->setAllowedTypes('foo', 'string'); $resolver->setAllowedValues('foo', ['bar', 'baz']); $resolver->setNormalizer('foo', fn (Options $options, $value) => (string) $value); + $resolver->setOptions('baz', function (OptionsResolver $baz) { + $baz->setRequired('foo'); + $baz->setDefaults(['foo' => true, 'bar' => true]); + }); } } diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 28810bbc7..977a8707c 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -878,7 +878,7 @@ public function testSubmitSingleExpandedRequired() $this->assertSame('b', $form->getData()); $this->assertSame('b', $form->getViewData()); - $this->assertEmpty($form->getExtraData()); + $this->assertSame([], $form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); @@ -906,7 +906,7 @@ public function testSubmitSingleExpandedRequiredInvalidChoice() $this->assertNull($form->getData()); $this->assertSame('foobar', $form->getViewData()); - $this->assertEmpty($form->getExtraData()); + $this->assertSame([], $form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); @@ -934,7 +934,7 @@ public function testSubmitSingleExpandedNonRequired() $this->assertSame('b', $form->getData()); $this->assertSame('b', $form->getViewData()); - $this->assertEmpty($form->getExtraData()); + $this->assertSame([], $form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertFalse($form['placeholder']->getData()); @@ -964,7 +964,7 @@ public function testSubmitSingleExpandedNonRequiredInvalidChoice() $this->assertNull($form->getData()); $this->assertSame('foobar', $form->getViewData()); - $this->assertEmpty($form->getExtraData()); + $this->assertSame([], $form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); @@ -1348,7 +1348,7 @@ public function testSubmitMultipleExpanded() $this->assertSame(['a', 'c'], $form->getData()); $this->assertSame(['a', 'c'], $form->getViewData()); - $this->assertEmpty($form->getExtraData()); + $this->assertSame([], $form->getExtraData()); $this->assertTrue($form->isSynchronized()); $this->assertTrue($form[0]->getData()); @@ -1375,7 +1375,7 @@ public function testSubmitMultipleExpandedInvalidScalarChoice() $this->assertNull($form->getData()); $this->assertSame('foobar', $form->getViewData()); - $this->assertEmpty($form->getExtraData()); + $this->assertSame([], $form->getExtraData()); $this->assertFalse($form->isSynchronized()); $this->assertFalse($form[0]->getData()); @@ -1402,7 +1402,7 @@ public function testSubmitMultipleExpandedInvalidArrayChoice() $this->assertSame(['a'], $form->getData()); $this->assertSame(['a'], $form->getViewData()); - $this->assertEmpty($form->getExtraData()); + $this->assertSame([], $form->getExtraData()); $this->assertFalse($form->isValid()); $this->assertTrue($form[0]->getData()); diff --git a/Tests/Extension/Core/Type/ColorTypeTest.php b/Tests/Extension/Core/Type/ColorTypeTest.php index 52382cea2..5cfab193e 100644 --- a/Tests/Extension/Core/Type/ColorTypeTest.php +++ b/Tests/Extension/Core/Type/ColorTypeTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\Extension\Core\Type\ColorType; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormErrorIterator; final class ColorTypeTest extends BaseTypeTestCase { @@ -30,7 +31,8 @@ public function testValidationShouldPass(bool $html5, ?string $submittedValue) $form->submit($submittedValue); - $this->assertEmpty($form->getErrors()); + $this->assertInstanceOf(FormErrorIterator::class, $form->getErrors()); + $this->assertCount(0, $form->getErrors()); } public static function validationShouldPassProvider(): array diff --git a/Tests/Extension/Core/Type/MoneyTypeTest.php b/Tests/Extension/Core/Type/MoneyTypeTest.php index f9112ffca..aa0d6c249 100644 --- a/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Extension\Core\Type\MoneyType; use Symfony\Component\Intl\Util\IntlTestHelper; @@ -146,4 +147,54 @@ public function testIntegerInputWithoutDivisor() $this->assertSame(1234567, $form->getData()); } + + public function testDefaultFormattingWithScaleAndStringInput() + { + $form = $this->factory->create(static::TESTED_TYPE, null, ['scale' => 2, 'input' => 'string']); + $form->setData('12345.67890'); + + $this->assertSame('12345.68', $form->createView()->vars['value']); + } + + public function testStringInputWithFloatData() + { + $this->expectException(TransformationFailedException::class); + $this->expectExceptionMessage('Expected a numeric string.'); + + $this->factory->create(static::TESTED_TYPE, 12345.6789, [ + 'input' => 'string', + 'scale' => 2, + ]); + } + + public function testStringInputWithIntData() + { + $this->expectException(TransformationFailedException::class); + $this->expectExceptionMessage('Expected a numeric string.'); + + $this->factory->create(static::TESTED_TYPE, 12345, [ + 'input' => 'string', + 'scale' => 2, + ]); + } + + public function testSubmitStringInputWithDefaultScale() + { + $form = $this->factory->create(static::TESTED_TYPE, null, ['input' => 'string']); + $form->submit('1.234'); + + $this->assertSame('1.23', $form->getData()); + $this->assertSame(1.23, $form->getNormData()); + $this->assertSame('1.23', $form->getViewData()); + } + + public function testSubmitStringInputWithScale() + { + $form = $this->factory->create(static::TESTED_TYPE, null, ['input' => 'string', 'scale' => 3]); + $form->submit('1.234'); + + $this->assertSame('1.234', $form->getData()); + $this->assertSame(1.234, $form->getNormData()); + $this->assertSame('1.234', $form->getViewData()); + } } diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 6a6a8be9c..48cbf743e 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Form\Extension\Core\DataMapper\DataMapper; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormErrorIterator; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormFactoryBuilder; use Symfony\Component\Form\FormFactoryInterface; @@ -65,7 +66,8 @@ public function testArrayCsrfToken() $validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Invalid.'); $validation->preSubmit($event); - $this->assertNotEmpty($this->form->getErrors()); + $this->assertInstanceOf(FormErrorIterator::class, $this->form->getErrors()); + $this->assertGreaterThan(0, \count($this->form->getErrors())); } public function testMaxPostSizeExceeded() @@ -74,7 +76,8 @@ public function testMaxPostSizeExceeded() $validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Error message', null, null, new ServerParamsPostMaxSizeExceeded()); $validation->preSubmit($event); - $this->assertEmpty($this->form->getErrors()); + $this->assertInstanceOf(FormErrorIterator::class, $this->form->getErrors()); + $this->assertCount(0, $this->form->getErrors()); } } diff --git a/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php b/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php index 14595e8cf..9841ac9fc 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorFunctionalTest.php @@ -88,7 +88,7 @@ public function testFieldConstraintsInvalidateFormIfFieldIsSubmitted() public function testNonCompositeConstraintValidatedOnce() { $form = $this->formFactory->create(TextType::class, null, [ - 'constraints' => [new NotBlank(['groups' => ['foo', 'bar']])], + 'constraints' => [new NotBlank(groups: ['foo', 'bar'])], 'validation_groups' => ['foo', 'bar'], ]); $form->submit(''); @@ -105,12 +105,8 @@ public function testCompositeConstraintValidatedInEachGroup() $form = $this->formFactory->create(FormType::class, null, [ 'constraints' => [ new Collection([ - 'field1' => new NotBlank([ - 'groups' => ['field1'], - ]), - 'field2' => new NotBlank([ - 'groups' => ['field2'], - ]), + 'field1' => new NotBlank(groups: ['field1']), + 'field2' => new NotBlank(groups: ['field2']), ]), ], 'validation_groups' => ['field1', 'field2'], @@ -136,12 +132,8 @@ public function testCompositeConstraintValidatedInSequence() $form = $this->formFactory->create(FormType::class, null, [ 'constraints' => [ new Collection([ - 'field1' => new NotBlank([ - 'groups' => ['field1'], - ]), - 'field2' => new NotBlank([ - 'groups' => ['field2'], - ]), + 'field1' => new NotBlank(groups: ['field1']), + 'field2' => new NotBlank(groups: ['field2']), ]), ], 'validation_groups' => new GroupSequence(['field1', 'field2']), @@ -167,10 +159,10 @@ public function testFieldsValidateInSequence() 'validation_groups' => new GroupSequence(['group1', 'group2']), ]) ->add('foo', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], + 'constraints' => [new Length(min: 10, groups: ['group1'])], ]) ->add('bar', TextType::class, [ - 'constraints' => [new NotBlank(['groups' => ['group2']])], + 'constraints' => [new NotBlank(groups: ['group2'])], ]) ; @@ -188,13 +180,13 @@ public function testFieldsValidateInSequenceWithNestedGroupsArray() 'validation_groups' => new GroupSequence([['group1', 'group2'], 'group3']), ]) ->add('foo', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], + 'constraints' => [new Length(min: 10, groups: ['group1'])], ]) ->add('bar', TextType::class, [ - 'constraints' => [new Length(['min' => 10, 'groups' => ['group2']])], + 'constraints' => [new Length(min: 10, groups: ['group2'])], ]) ->add('baz', TextType::class, [ - 'constraints' => [new NotBlank(['groups' => ['group3']])], + 'constraints' => [new NotBlank(groups: ['group3'])], ]) ; @@ -214,13 +206,11 @@ public function testConstraintsInDifferentGroupsOnSingleField() ]) ->add('foo', TextType::class, [ 'constraints' => [ - new NotBlank([ - 'groups' => ['group1'], - ]), - new Length([ - 'groups' => ['group2'], - 'max' => 3, - ]), + new NotBlank(groups: ['group1']), + new Length( + groups: ['group2'], + max: 3, + ), ], ]); $form->submit([ @@ -242,13 +232,11 @@ public function testConstraintsInDifferentGroupsOnSingleFieldWithAdditionalField ->add('bar') ->add('foo', TextType::class, [ 'constraints' => [ - new NotBlank([ - 'groups' => ['group1'], - ]), - new Length([ - 'groups' => ['group2'], - 'max' => 3, - ]), + new NotBlank(groups: ['group1']), + new Length( + groups: ['group2'], + max: 3, + ), ], ]); $form->submit([ @@ -268,11 +256,11 @@ public function testCascadeValidationToChildFormsUsingPropertyPaths() 'validation_groups' => ['group1', 'group2'], ]) ->add('field1', null, [ - 'constraints' => [new NotBlank(['groups' => 'group1'])], + 'constraints' => [new NotBlank(groups: ['group1'])], 'property_path' => '[foo]', ]) ->add('field2', null, [ - 'constraints' => [new NotBlank(['groups' => 'group2'])], + 'constraints' => [new NotBlank(groups: ['group2'])], 'property_path' => '[bar]', ]) ; @@ -359,11 +347,11 @@ public function testCascadeValidationToChildFormsUsingPropertyPathsValidatedInSe 'validation_groups' => new GroupSequence(['group1', 'group2']), ]) ->add('field1', null, [ - 'constraints' => [new NotBlank(['groups' => 'group1'])], + 'constraints' => [new NotBlank(groups: ['group1'])], 'property_path' => '[foo]', ]) ->add('field2', null, [ - 'constraints' => [new NotBlank(['groups' => 'group2'])], + 'constraints' => [new NotBlank(groups: ['group2'])], 'property_path' => '[bar]', ]) ; @@ -384,9 +372,7 @@ public function testContextIsPopulatedWithFormBeingValidated() { $form = $this->formFactory->create(FormType::class) ->add('field1', null, [ - 'constraints' => [new Expression([ - 'expression' => '!this.getParent().get("field2").getData()', - ])], + 'constraints' => [new Expression(expression: '!this.getParent().get("field2").getData()')], ]) ->add('field2') ; @@ -407,10 +393,10 @@ public function testContextIsPopulatedWithFormBeingValidatedUsingGroupSequence() 'validation_groups' => new GroupSequence(['group1']), ]) ->add('field1', null, [ - 'constraints' => [new Expression([ - 'expression' => '!this.getParent().get("field2").getData()', - 'groups' => ['group1'], - ])], + 'constraints' => [new Expression( + expression: '!this.getParent().get("field2").getData()', + groups: ['group1'], + )], ]) ->add('field2') ; diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 86b53ac3a..b438c0d8f 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -70,9 +70,9 @@ public function testValidate() public function testValidateConstraints() { $object = new \stdClass(); - $constraint1 = new NotNull(['groups' => ['group1', 'group2']]); - $constraint2 = new NotBlank(['groups' => 'group2']); - $constraint3 = new Length(['groups' => 'group2', 'min' => 3]); + $constraint1 = new NotNull(groups: ['group1', 'group2']); + $constraint2 = new NotBlank(groups: ['group2']); + $constraint3 = new Length(groups: ['group2'], min: 3); $options = [ 'validation_groups' => ['group1', 'group2'], @@ -156,8 +156,8 @@ public function testMissingConstraintIndex() public function testValidateConstraintsOptionEvenIfNoValidConstraint() { $object = new \stdClass(); - $constraint1 = new NotNull(['groups' => ['group1', 'group2']]); - $constraint2 = new NotBlank(['groups' => 'group2']); + $constraint1 = new NotNull(groups: ['group1', 'group2']); + $constraint2 = new NotBlank(groups: ['group2']); $parent = $this->getBuilder('parent', null) ->setCompound(true) @@ -684,7 +684,7 @@ public function getValidationGroups(FormInterface $form) public function testCauseForNotAllowedExtraFieldsIsTheFormConstraint() { $form = $this - ->getBuilder('form', null, ['constraints' => [new NotBlank(['groups' => ['foo']])]]) + ->getBuilder('form', null, ['constraints' => [new NotBlank(groups: ['foo'])]]) ->setCompound(true) ->setDataMapper(new DataMapper()) ->getForm(); diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index a1d1a3840..2dec87b5c 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -84,8 +84,8 @@ public function testGroupSequenceWithConstraintsOption() ->create(FormTypeTest::TESTED_TYPE, null, ['validation_groups' => new GroupSequence(['First', 'Second'])]) ->add('field', TextTypeTest::TESTED_TYPE, [ 'constraints' => [ - new Length(['min' => 10, 'groups' => ['First']]), - new NotBlank(['groups' => ['Second']]), + new Length(min: 10, groups: ['First']), + new NotBlank(groups: ['Second']), ], ]) ; @@ -102,7 +102,7 @@ public function testManyFieldsGroupSequenceWithConstraintsOption() { $formMetadata = new ClassMetadata(Form::class); $authorMetadata = (new ClassMetadata(Author::class)) - ->addPropertyConstraint('firstName', new NotBlank(['groups' => 'Second'])) + ->addPropertyConstraint('firstName', new NotBlank(groups: ['Second'])) ; $metadataFactory = $this->createMock(MetadataFactoryInterface::class); $metadataFactory->expects($this->any()) @@ -131,12 +131,12 @@ public function testManyFieldsGroupSequenceWithConstraintsOption() ->add('firstName', TextTypeTest::TESTED_TYPE) ->add('lastName', TextTypeTest::TESTED_TYPE, [ 'constraints' => [ - new Length(['min' => 10, 'groups' => ['First']]), + new Length(min: 10, groups: ['First']), ], ]) ->add('australian', TextTypeTest::TESTED_TYPE, [ 'constraints' => [ - new NotBlank(['groups' => ['Second']]), + new NotBlank(groups: ['Second']), ], ]) ; diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index c561cd76f..1d0e0f872 100644 --- a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -96,8 +96,8 @@ public static function guessRequiredProvider() [new NotNull(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)], [new NotBlank(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)], [new IsTrue(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)], - [new Length(['min' => 10, 'max' => 10]), new ValueGuess(false, Guess::LOW_CONFIDENCE)], - [new Range(['min' => 1, 'max' => 20]), new ValueGuess(false, Guess::LOW_CONFIDENCE)], + [new Length(min: 10, max: 10), new ValueGuess(false, Guess::LOW_CONFIDENCE)], + [new Range(min: 1, max: 20), new ValueGuess(false, Guess::LOW_CONFIDENCE)], ]; } @@ -122,7 +122,7 @@ public function testGuessRequiredReturnsFalseForUnmappedProperties() public function testGuessMaxLengthForConstraintWithMaxValue() { - $constraint = new Length(['max' => '2']); + $constraint = new Length(max: '2'); $result = $this->guesser->guessMaxLengthForConstraint($constraint); $this->assertInstanceOf(ValueGuess::class, $result); @@ -132,7 +132,7 @@ public function testGuessMaxLengthForConstraintWithMaxValue() public function testGuessMaxLengthForConstraintWithMinValue() { - $constraint = new Length(['min' => '2']); + $constraint = new Length(min: '2'); $result = $this->guesser->guessMaxLengthForConstraint($constraint); $this->assertNull($result); @@ -141,7 +141,7 @@ public function testGuessMaxLengthForConstraintWithMinValue() public function testGuessMimeTypesForConstraintWithMimeTypesValue() { $mimeTypes = ['image/png', 'image/jpeg']; - $constraint = new File(['mimeTypes' => $mimeTypes]); + $constraint = new File(mimeTypes: $mimeTypes); $typeGuess = $this->guesser->guessTypeForConstraint($constraint); $this->assertInstanceOf(TypeGuess::class, $typeGuess); $this->assertArrayHasKey('attr', $typeGuess->getOptions()); @@ -159,7 +159,7 @@ public function testGuessMimeTypesForConstraintWithoutMimeTypesValue() public function testGuessMimeTypesForConstraintWithMimeTypesStringValue() { - $constraint = new File(['mimeTypes' => 'image/*']); + $constraint = new File(mimeTypes: 'image/*'); $typeGuess = $this->guesser->guessTypeForConstraint($constraint); $this->assertInstanceOf(TypeGuess::class, $typeGuess); $this->assertArrayHasKey('attr', $typeGuess->getOptions()); @@ -169,7 +169,7 @@ public function testGuessMimeTypesForConstraintWithMimeTypesStringValue() public function testGuessMimeTypesForConstraintWithMimeTypesEmptyStringValue() { - $constraint = new File(['mimeTypes' => '']); + $constraint = new File(mimeTypes: ''); $typeGuess = $this->guesser->guessTypeForConstraint($constraint); $this->assertInstanceOf(TypeGuess::class, $typeGuess); $this->assertArrayNotHasKey('attr', $typeGuess->getOptions()); diff --git a/Tests/Fixtures/Descriptor/default_option_with_normalizer.json b/Tests/Fixtures/Descriptor/default_option_with_normalizer.json index 0ac903a95..25b7c4525 100644 --- a/Tests/Fixtures/Descriptor/default_option_with_normalizer.json +++ b/Tests/Fixtures/Descriptor/default_option_with_normalizer.json @@ -7,5 +7,6 @@ "bool", "string" ], - "has_normalizer": true + "has_normalizer": true, + "has_nested_options": false } diff --git a/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt b/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt index 0f6f1f40e..cd41f47a8 100644 --- a/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt +++ b/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt @@ -25,4 +25,6 @@ Symfony\Component\Form\Extension\Core\Type\ChoiceType (choice_translation_domain } %s ] %s ---------------- -----------%s + Nested Options - %s + ---------------- -----------%s diff --git a/Tests/Fixtures/Descriptor/deprecated_option.json b/Tests/Fixtures/Descriptor/deprecated_option.json index b3b0cf3ec..5c88933f9 100644 --- a/Tests/Fixtures/Descriptor/deprecated_option.json +++ b/Tests/Fixtures/Descriptor/deprecated_option.json @@ -2,5 +2,6 @@ "deprecated": true, "deprecation_message": "The option \"bar\" is deprecated.", "required": false, - "has_normalizer": false + "has_normalizer": false, + "has_nested_options": false } diff --git a/Tests/Fixtures/Descriptor/deprecated_option.txt b/Tests/Fixtures/Descriptor/deprecated_option.txt index 31ef796f9..f5da39c70 100644 --- a/Tests/Fixtures/Descriptor/deprecated_option.txt +++ b/Tests/Fixtures/Descriptor/deprecated_option.txt @@ -21,4 +21,6 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (bar) Allowed values - --------------------- ----------------------------------- Normalizers - - --------------------- ----------------------------------- + --------------------- ----------------------------------- + Nested Options - + --------------------- ----------------------------------- diff --git a/Tests/Fixtures/Descriptor/nested_option.json b/Tests/Fixtures/Descriptor/nested_option.json new file mode 100644 index 000000000..a6fa2a93a --- /dev/null +++ b/Tests/Fixtures/Descriptor/nested_option.json @@ -0,0 +1,23 @@ +{ + "required": false, + "default": [], + "is_lazy": false, + "has_normalizer": false, + "has_nested_options": true, + "nested_options": { + "foo": { + "required": true, + "default": true, + "is_lazy": false, + "has_normalizer": false, + "has_nested_options": false + }, + "bar": { + "required": false, + "default": true, + "is_lazy": false, + "has_normalizer": false, + "has_nested_options": false + } + } +} diff --git a/Tests/Fixtures/Descriptor/nested_option.txt b/Tests/Fixtures/Descriptor/nested_option.txt new file mode 100644 index 000000000..0f698abfc --- /dev/null +++ b/Tests/Fixtures/Descriptor/nested_option.txt @@ -0,0 +1,21 @@ +Symfony\Component\Form\Tests\Console\Descriptor\FooType (baz) +============================================================= + + ---------------- ---------- + Info - + ---------------- ---------- + Required false + ---------------- ---------- + Default [] + ---------------- ---------- + Allowed types - + ---------------- ---------- + Allowed values - + ---------------- ---------- + Normalizers - + ---------------- ---------- + Nested Options [ + "foo", + "bar" + ] + ---------------- ---------- diff --git a/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json b/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json index c41e377ac..bc79122e1 100644 --- a/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json +++ b/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json @@ -2,5 +2,6 @@ "required": false, "default": null, "is_lazy": true, - "has_normalizer": false + "has_normalizer": false, + "has_nested_options": false } diff --git a/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt b/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt index cedca25a6..8bf9cb8c8 100644 --- a/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt +++ b/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt @@ -23,6 +23,8 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (empty_data) ---------------- ----------------------%s Allowed values - %s ---------------- ----------------------%s - Normalizers - %s + Normalizers - %s + ---------------- ----------------------%s + Nested Options - %s ---------------- ----------------------%s diff --git a/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json b/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json index 126933c6b..5aad5becb 100644 --- a/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json +++ b/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json @@ -7,5 +7,6 @@ "bar", "baz" ], - "has_normalizer": true + "has_normalizer": true, + "has_nested_options": false } diff --git a/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt b/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt index fd2f8f3f1..a8371243b 100644 --- a/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt +++ b/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt @@ -27,4 +27,5 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (foo) } %s ] %s ---------------- -----------%s - + Nested Options - %s + ---------------- -----------%s diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index 023cf77d6..9234d8775 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -173,8 +173,8 @@ public function testGetFormConfigErasesReferences() $children = $reflClass->getProperty('children'); $unresolvedChildren = $reflClass->getProperty('unresolvedChildren'); - $this->assertEmpty($children->getValue($config)); - $this->assertEmpty($unresolvedChildren->getValue($config)); + $this->assertSame([], $children->getValue($config)); + $this->assertSame([], $unresolvedChildren->getValue($config)); } public function testGetButtonBuilderBeforeExplicitlyResolvingAllChildren() diff --git a/composer.json b/composer.json index 40c021d91..f4403ba74 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/options-resolver": "^6.4|^7.0", + "symfony/options-resolver": "^7.3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-icu": "^1.21", "symfony/polyfill-mbstring": "~1.0",