diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index b11fa38f99..edde960a38 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -279,7 +279,7 @@ class Form extends Link implements \ArrayAccess * * @param string $name The field name * - * @return FormField The field instance + * @return FormField|FormField[]|FormField[][] The value of the field * * @throws \InvalidArgumentException When field is not present in this form */ @@ -323,7 +323,7 @@ class Form extends Link implements \ArrayAccess * * @param string $name The field name * - * @return FormField The associated Field instance + * @return FormField|FormField[]|FormField[][] The value of the field * * @throws \InvalidArgumentException if the field does not exist */ diff --git a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php index f8764119a2..7cfdd53494 100644 --- a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php +++ b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php @@ -66,7 +66,7 @@ class FormFieldRegistry /** * Returns the value of the field based on the fully qualifed name and its children. * - * @return mixed The value of the field + * @return FormField|FormField[]|FormField[][] The value of the field * * @throws \InvalidArgumentException if the field does not exist */ diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 9975b91afe..52e778bed9 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DomCrawler\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Component\DomCrawler\Field\TextareaFormField; use Symfony\Component\DomCrawler\Form; use Symfony\Component\DomCrawler\FormFieldRegistry; @@ -965,7 +966,7 @@ class FormTest extends TestCase return $dom; } - public function testgetPhpValuesWithEmptyTextarea() + public function testGetPhpValuesWithEmptyTextarea() { $dom = new \DOMDocument(); $dom->loadHTML(' @@ -980,4 +981,34 @@ class FormTest extends TestCase $form = new Form($nodes->item(0), 'http://example.com'); $this->assertEquals($form->getPhpValues(), ['example' => '']); } + + public function testGetReturnTypes() + { + $dom = new \DOMDocument(); + $dom->loadHTML(' + +
+ ' + ); + + $nodes = $dom->getElementsByTagName('form'); + $form = new Form($nodes->item(0), 'http://example.com'); + + // FormField + $this->assertInstanceOf(TextareaFormField::class, $textareaFormField = $form->get('foo[collection][0][bar]')); + + // Array of FormField + $this->assertSame([ + 'bar' => $textareaFormField, + ], $form->get('foo[collection][0]')); + + // Array of array of FormField + $this->assertSame([ + [ + 'bar' => $textareaFormField, + ], + ], $form->get('foo[collection]')); + } } diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 8e0e1454e0..59d59093e0 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -279,7 +279,7 @@ class NumberToLocalizedStringTransformer implements DataTransformerInterface break; } - $number /= $roundingCoef; + $number = 1 === $roundingCoef ? (int) $number : $number / $roundingCoef; } return $number; diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index cb3f5d890e..80da74ed56 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -370,7 +370,7 @@ class NumberToLocalizedStringTransformerTest extends TestCase { $transformer = new NumberToLocalizedStringTransformer($scale, null, $roundingMode); - $this->assertEquals($output, $transformer->reverseTransform($input)); + $this->assertSame($output, $transformer->reverseTransform($input)); } public function testReverseTransformDoesNotRoundIfNoScale() diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index f0288072f6..6905354a7e 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Serializer\Encoder; +use Symfony\Component\Serializer\Exception\BadMethodCallException; use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\SerializerAwareInterface; use Symfony\Component\Serializer\SerializerAwareTrait; @@ -413,7 +414,7 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa $removeEmptyTags = $this->context[self::REMOVE_EMPTY_TAGS] ?? $this->defaultContext[self::REMOVE_EMPTY_TAGS] ?? false; $encoderIgnoredNodeTypes = $this->context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES]; - if (\is_array($data) || ($data instanceof \Traversable && !$this->serializer->supportsNormalization($data, $this->format))) { + if (\is_array($data) || ($data instanceof \Traversable && (null === $this->serializer || !$this->serializer->supportsNormalization($data, $this->format)))) { foreach ($data as $key => $data) { //Ah this is the magic @ attribute types. if (0 === strpos($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) { @@ -452,6 +453,10 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa } if (\is_object($data)) { + if (null === $this->serializer) { + throw new BadMethodCallException(sprintf('The serializer needs to be set to allow %s() to be used with object data.', __METHOD__)); + } + $data = $this->serializer->normalize($data, $this->format, $this->context); if (null !== $data && !is_scalar($data)) { return $this->buildXml($parentNode, $data, $xmlRootNodeName); @@ -514,6 +519,10 @@ class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwa } elseif ($val instanceof \Traversable) { $this->buildXml($node, $val); } elseif (\is_object($val)) { + if (null === $this->serializer) { + throw new BadMethodCallException(sprintf('The serializer needs to be set to allow %s() to be used with object data.', __METHOD__)); + } + return $this->selectNodeType($node, $this->serializer->normalize($val, $this->format, $this->context)); } elseif (is_numeric($val)) { return $this->appendText($node, (string) $val); diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index d4ea8fd465..1d416a227d 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -68,6 +68,10 @@ class ArrayDenormalizer implements ContextAwareDenormalizerInterface, Serializer */ public function supportsDenormalization($data, $type, $format = null, array $context = []): bool { + if (null === $this->serializer) { + throw new BadMethodCallException(sprintf('The serializer needs to be set to allow %s() to be used.', __METHOD__)); + } + return '[]' === substr($type, -2) && $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); } diff --git a/src/Symfony/Component/Validator/ConstraintValidator.php b/src/Symfony/Component/Validator/ConstraintValidator.php index 458351fe2e..db0ccb60a8 100644 --- a/src/Symfony/Component/Validator/ConstraintValidator.php +++ b/src/Symfony/Component/Validator/ConstraintValidator.php @@ -21,8 +21,8 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; abstract class ConstraintValidator implements ConstraintValidatorInterface { /** - * Whether to format {@link \DateTime} objects as RFC-3339 dates - * ("Y-m-d H:i:s"). + * Whether to format {@link \DateTime} objects, either with the {@link \IntlDateFormatter} + * (if it is available) or as RFC-3339 dates ("Y-m-d H:i:s"). */ const PRETTY_DATE = 1; @@ -69,7 +69,8 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface * in double quotes ("). Objects, arrays and resources are formatted as * "object", "array" and "resource". If the $format bitmask contains * the PRETTY_DATE bit, then {@link \DateTime} objects will be formatted - * as RFC-3339 dates ("Y-m-d H:i:s"). + * with the {@link \IntlDateFormatter}. If it is not available, they will be + * formatted as RFC-3339 dates ("Y-m-d H:i:s"). * * Be careful when passing message parameters to a constraint violation * that (may) contain objects, arrays or resources. These parameters diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf index 0702e8dfcd..a546b86c78 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf @@ -370,6 +370,10 @@