diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 2ec204f6f1..84151a2099 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -414,6 +414,7 @@ + @@ -444,12 +445,21 @@ + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php index 68ff360746..0aff440e85 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger_transports.php @@ -3,6 +3,7 @@ $container->loadFromExtension('framework', [ 'serializer' => true, 'messenger' => [ + 'failure_transport' => 'failed', 'serializer' => [ 'default_serializer' => 'messenger.transport.symfony_serializer', ], @@ -12,7 +13,14 @@ $container->loadFromExtension('framework', [ 'dsn' => 'amqp://localhost/%2f/messages?exchange_name=exchange_name', 'options' => ['queue' => ['name' => 'Queue']], 'serializer' => 'messenger.transport.native_php_serializer', + 'retry_strategy' => [ + 'max_retries' => 10, + 'delay' => 7, + 'multiplier' => 3, + 'max_delay' => 100, + ], ], + 'failed' => 'in-memory:///', 'redis' => 'redis://127.0.0.1:6379/messages', ], ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml index bb698cbc17..837db14c1c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/messenger_transports.xml @@ -7,7 +7,7 @@ - + @@ -16,7 +16,9 @@ Queue + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml index 2fc1f48265..daab75bd87 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger_transports.yml @@ -1,6 +1,7 @@ framework: serializer: true messenger: + failure_transport: failed serializer: default_serializer: messenger.transport.symfony_serializer transports: @@ -11,4 +12,10 @@ framework: queue: name: Queue serializer: 'messenger.transport.native_php_serializer' + retry_strategy: + max_retries: 10 + delay: 7 + multiplier: 3 + max_delay: 100 + failed: 'in-memory:///' redis: 'redis://127.0.0.1:6379/messages' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 0ee3b892aa..657b67e8f0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -627,6 +627,13 @@ abstract class FrameworkExtensionTest extends TestCase $this->assertSame('redis://127.0.0.1:6379/messages', $transportArguments[0]); $this->assertTrue($container->hasDefinition('messenger.transport.redis.factory')); + + $this->assertSame(10, $container->getDefinition('messenger.retry.multiplier_retry_strategy.customised')->getArgument(0)); + $this->assertSame(7, $container->getDefinition('messenger.retry.multiplier_retry_strategy.customised')->getArgument(1)); + $this->assertSame(3, $container->getDefinition('messenger.retry.multiplier_retry_strategy.customised')->getArgument(2)); + $this->assertSame(100, $container->getDefinition('messenger.retry.multiplier_retry_strategy.customised')->getArgument(3)); + + $this->assertEquals(new Reference('messenger.transport.failed'), $container->getDefinition('messenger.failure.send_failed_message_to_failure_transport_listener')->getArgument(0)); } public function testMessengerRouting() diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index 6d8cced74f..56d10108c1 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -273,7 +273,7 @@ class Form extends Link implements \ArrayAccess /** * Gets a named field. * - * @return FormField The field instance + * @return FormField|FormField[]|FormField[][] The value of the field * * @throws \InvalidArgumentException When field is not present in this form */ @@ -317,7 +317,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/Dotenv/README.md b/src/Symfony/Component/Dotenv/README.md index c21223b04e..10bfff14ba 100644 --- a/src/Symfony/Component/Dotenv/README.md +++ b/src/Symfony/Component/Dotenv/README.md @@ -2,7 +2,7 @@ Dotenv Component ================ Symfony Dotenv parses `.env` files to make environment variables stored in them -accessible via `$_SERVER`, `$_ENV` and optionally `getenv()`. +accessible via `$_SERVER` or `$_ENV`. Resources --------- diff --git a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php index 024034c13a..e210acdf10 100644 --- a/src/Symfony/Component/ErrorHandler/DebugClassLoader.php +++ b/src/Symfony/Component/ErrorHandler/DebugClassLoader.php @@ -427,17 +427,17 @@ class DebugClassLoader } } - if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) { + if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+([\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) { foreach ($notice as $method) { - $static = '' !== $method[1]; - $name = $method[2]; - $description = $method[3] ?? null; + $static = '' !== $method[1] && !empty($method[2]); + $name = $method[3]; + $description = $method[4] ?? null; if (false === strpos($name, '(')) { $name .= '()'; } if (null !== $description) { $description = trim($description); - if (!isset($method[4])) { + if (!isset($method[5])) { $description .= '.'; } } diff --git a/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php index adf55432ee..d0ff0afba8 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php @@ -325,6 +325,7 @@ class DebugClassLoaderTest extends TestCase restore_error_handler(); $this->assertSame([ + 'Class "Test\Symfony\Component\ErrorHandler\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\ErrorHandler\Tests\Fixtures\VirtualInterface::staticReturningMethod()".', 'Class "Test\Symfony\Component\ErrorHandler\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\ErrorHandler\Tests\Fixtures\VirtualInterface::sameLineInterfaceMethodNoBraces()".', 'Class "Test\Symfony\Component\ErrorHandler\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\ErrorHandler\Tests\Fixtures\VirtualInterface::newLineInterfaceMethod()": Some description!', 'Class "Test\Symfony\Component\ErrorHandler\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\ErrorHandler\Tests\Fixtures\VirtualInterface::newLineInterfaceMethodNoBraces()": Description.', diff --git a/src/Symfony/Component/ErrorHandler/Tests/Fixtures/VirtualInterface.php b/src/Symfony/Component/ErrorHandler/Tests/Fixtures/VirtualInterface.php index fd1c8ba04e..5c9136081f 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/Fixtures/VirtualInterface.php +++ b/src/Symfony/Component/ErrorHandler/Tests/Fixtures/VirtualInterface.php @@ -4,6 +4,7 @@ namespace Symfony\Component\ErrorHandler\Tests\Fixtures; /** * @method string interfaceMethod() + * @method static staticReturningMethod() * @method sameLineInterfaceMethod($arg) * @method sameLineInterfaceMethodNoBraces * @@ -25,7 +26,7 @@ namespace Symfony\Component\ErrorHandler\Tests\Fixtures; * * Static * @method static Foo&Bar staticMethod() - * @method static staticMethodNoBraces + * @method static mixed staticMethodNoBraces * @method static \stdClass staticMethodTyped(int $arg) Description * @method static \stdClass[] staticMethodTypedNoBraces */ 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 5620dc5c1e..33942d73fe 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; @@ -368,7 +369,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))) { @@ -407,6 +408,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); @@ -469,6 +474,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 935e7a0323..ad5090faa5 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, string $type, string $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 4d66776839..02a8261eff 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 @@ This value is not a valid hostname. Dieser Wert ist kein gültiger Hostname. + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Die Anzahl an Elementen in dieser Sammlung sollte ein Vielfaches von {{ compared_value }} sein. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf index 95dd7d6665..ead79d2cd7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf @@ -362,6 +362,18 @@ This password has been leaked in a data breach, it must not be used. Please use another password. Mật khẩu này đã bị rò rỉ dữ liệu, không được sử dụng nữa. Xin vui lòng sử dụng mật khẩu khác. + + This value should be between {{ min }} and {{ max }}. + Giá trị này nên thuộc giữa {{ min }} và {{ max }}. + + + This value is not a valid hostname. + Giá trị này không phải là tên máy chủ hợp lệ. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Số lượng các phần tử trong bộ sưu tập này nên là bội số của {{compared_value}}. +