From e31aeebbba2bae807522e7247d1ec6529228d2e9 Mon Sep 17 00:00:00 2001 From: Mathias Arlaud Date: Thu, 23 Nov 2023 08:57:08 +0100 Subject: [PATCH 01/39] [PropertyAccessor] Fix unexpected collection when generics --- .../Tests/Extractor/PhpDocExtractorTest.php | 5 +++++ .../Tests/Extractor/PhpStanExtractorTest.php | 7 ++++++- .../Tests/Extractor/ReflectionExtractorTest.php | 3 +++ .../Component/PropertyInfo/Tests/Fixtures/Dummy.php | 5 +++++ .../PropertyInfo/Tests/Fixtures/DummyUnionType.php | 2 +- .../PropertyInfo/Util/PhpDocTypeHelper.php | 13 ++++++++++--- .../PropertyInfo/Util/PhpStanTypeHelper.php | 9 ++++++++- .../Tests/DeserializeNestedArrayOfObjectsTest.php | 2 +- 8 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index f71664d5a3547..57869e40819bb 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -428,6 +428,11 @@ public function testUnknownPseudoType() $this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'scalar')], $this->extractor->getTypes(PseudoTypeDummy::class, 'unknownPseudoType')); } + public function testGenericInterface() + { + $this->assertNull($this->extractor->getTypes(Dummy::class, 'genericInterface')); + } + protected static function isPhpDocumentorV5() { if (class_exists(InvalidTag::class)) { diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php index d8fa9b9192c51..51e28ed4b8373 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php @@ -388,7 +388,7 @@ public static function unionTypesProvider(): array ['b', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]], ['c', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]], ['d', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])])]], - ['e', [new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class, true, [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])], [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING, false, null, true, [], [new Type(Type::BUILTIN_TYPE_OBJECT, false, DefaultValue::class)])])]), new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]], + ['e', [new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class, false, [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])], [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_OBJECT, false, \Traversable::class, true, [], [new Type(Type::BUILTIN_TYPE_OBJECT, false, DefaultValue::class)])])]), new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]], ['f', null], ['g', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]], ]; @@ -427,6 +427,11 @@ public static function intRangeTypeProvider(): array ['c', [new Type(Type::BUILTIN_TYPE_INT)]], ]; } + + public function testGenericInterface() + { + $this->assertNull($this->extractor->getTypes(Dummy::class, 'genericInterface')); + } } class PhpStanOmittedParamTagTypeDocBlock diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index d3d57514a02c9..06e8bc53f87b5 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -73,6 +73,7 @@ public function testGetProperties() 'arrayOfMixed', 'listOfStrings', 'parentAnnotation', + 'genericInterface', 'foo', 'foo2', 'foo3', @@ -137,6 +138,7 @@ public function testGetPropertiesWithCustomPrefixes() 'arrayOfMixed', 'listOfStrings', 'parentAnnotation', + 'genericInterface', 'foo', 'foo2', 'foo3', @@ -190,6 +192,7 @@ public function testGetPropertiesWithNoPrefixes() 'arrayOfMixed', 'listOfStrings', 'parentAnnotation', + 'genericInterface', 'foo', 'foo2', 'foo3', diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index 06c0783a3c8f8..cf0c791784695 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -165,6 +165,11 @@ class Dummy extends ParentDummy */ public $parentAnnotation; + /** + * @var \BackedEnum + */ + public $genericInterface; + public static function getStatic() { } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php index 86ddb8a1650eb..7e2e1aa3ec8f7 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php @@ -40,7 +40,7 @@ class DummyUnionType public $d; /** - * @var (Dummy, (int | (string)[])> | ParentDummy | null) + * @var (Dummy, (int | (\Traversable)[])> | ParentDummy | null) */ public $e; diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php index 6020be0b80a3c..dc8a941b5e7fc 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php @@ -102,9 +102,9 @@ public function getTypes(DocType $varType): array /** * Creates a {@see Type} from a PHPDoc type. */ - private function createType(DocType $type, bool $nullable, ?string $docType = null): ?Type + private function createType(DocType $type, bool $nullable): ?Type { - $docType = $docType ?? (string) $type; + $docType = (string) $type; if ($type instanceof Collection) { $fqsen = $type->getFqsen(); @@ -115,10 +115,17 @@ private function createType(DocType $type, bool $nullable, ?string $docType = nu [$phpType, $class] = $this->getPhpTypeAndClass((string) $fqsen); + $collection = \is_a($class, \Traversable::class, true) || \is_a($class, \ArrayAccess::class, true); + + // it's safer to fall back to other extractors if the generic type is too abstract + if (!$collection && !class_exists($class)) { + return null; + } + $keys = $this->getTypes($type->getKeyType()); $values = $this->getTypes($type->getValueType()); - return new Type($phpType, $nullable, $class, true, $keys, $values); + return new Type($phpType, $nullable, $class, $collection, $keys, $values); } // Cannot guess diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php index 256122af759b7..6171530abadc7 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php @@ -121,6 +121,13 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array return [$mainType]; } + $collection = $mainType->isCollection() || \in_array($mainType->getClassName(), [\Traversable::class, \Iterator::class, \IteratorAggregate::class, \ArrayAccess::class, \Generator::class], true); + + // it's safer to fall back to other extractors if the generic type is too abstract + if (!$collection && !class_exists($mainType->getClassName())) { + return []; + } + $collectionKeyTypes = $mainType->getCollectionKeyTypes(); $collectionKeyValues = []; if (1 === \count($node->genericTypes)) { @@ -136,7 +143,7 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array } } - return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), true, $collectionKeyTypes, $collectionKeyValues)]; + return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), $collection, $collectionKeyTypes, $collectionKeyValues)]; } if ($node instanceof ArrayShapeNode) { return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]; diff --git a/src/Symfony/Component/Serializer/Tests/DeserializeNestedArrayOfObjectsTest.php b/src/Symfony/Component/Serializer/Tests/DeserializeNestedArrayOfObjectsTest.php index 8da1b471bd567..57f2b568ef44e 100644 --- a/src/Symfony/Component/Serializer/Tests/DeserializeNestedArrayOfObjectsTest.php +++ b/src/Symfony/Component/Serializer/Tests/DeserializeNestedArrayOfObjectsTest.php @@ -156,7 +156,7 @@ class ZooWithKeyTypes public $animalsString = []; /** @var array */ public $animalsUnion = []; - /** @var \stdClass */ + /** @var \Traversable */ public $animalsGenerics = []; } From 348f11a86745623f6c18a45330160c894eb110d6 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Sat, 25 May 2024 13:44:26 +0200 Subject: [PATCH 02/39] [PhpUnitBridge] Fix error handler triggered outside of tests --- .../Bridge/PhpUnit/DeprecationErrorHandler.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 05c67b7b37e6e..95312e2b3ce80 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -368,22 +368,26 @@ private static function getPhpUnitErrorHandler() if ('PHPUnit\Util\ErrorHandler::handleError' === $eh) { return $eh; - } elseif (ErrorHandler::class === $eh) { - return function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) { - ErrorHandler::instance()($errorNumber, $errorString, $errorFile, $errorLine); - - return true; - }; } foreach (debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { - if (isset($frame['object']) && $frame['object'] instanceof TestResult) { + if (!isset($frame['object'])) { + continue; + } + + if ($frame['object'] instanceof TestResult) { return new $eh( $frame['object']->getConvertDeprecationsToExceptions(), $frame['object']->getConvertErrorsToExceptions(), $frame['object']->getConvertNoticesToExceptions(), $frame['object']->getConvertWarningsToExceptions() ); + } elseif (ErrorHandler::class === $eh && $frame['object'] instanceof TestCase) { + return function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) { + ErrorHandler::instance()($errorNumber, $errorString, $errorFile, $errorLine); + + return true; + }; } } From e10aa0ea934f05d5b792681d17a89425c7a3bf41 Mon Sep 17 00:00:00 2001 From: "Jonathan H. Wage" Date: Tue, 5 Mar 2024 14:09:36 -0600 Subject: [PATCH 03/39] [Messenger] [Amqp] Handle AMQPConnectionException when publishing a message. --- .../Amqp/Tests/Transport/ConnectionTest.php | 67 +++++++++++++++++++ .../Bridge/Amqp/Transport/Connection.php | 56 +++++++++++----- 2 files changed, 108 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php index 9de6fa8ca0919..322bf6f4df84b 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php @@ -813,6 +813,73 @@ public function testItCanBeConstructedWithTLSOptionsAndNonTLSDsn() ); } + public function testItCanRetryPublishWhenAMQPConnectionExceptionIsThrown() + { + $factory = new TestAmqpFactory( + $amqpConnection = $this->createMock(\AMQPConnection::class), + $amqpChannel = $this->createMock(\AMQPChannel::class), + $amqpQueue = $this->createMock(\AMQPQueue::class), + $amqpExchange = $this->createMock(\AMQPExchange::class) + ); + + $amqpExchange->expects($this->exactly(2)) + ->method('publish') + ->willReturnOnConsecutiveCalls( + $this->throwException(new \AMQPConnectionException('a socket error occurred')), + null + ); + + $connection = Connection::fromDsn('amqp://localhost', [], $factory); + $connection->publish('body'); + } + + public function testItCanRetryPublishWithDelayWhenAMQPConnectionExceptionIsThrown() + { + $factory = new TestAmqpFactory( + $amqpConnection = $this->createMock(\AMQPConnection::class), + $amqpChannel = $this->createMock(\AMQPChannel::class), + $amqpQueue = $this->createMock(\AMQPQueue::class), + $amqpExchange = $this->createMock(\AMQPExchange::class) + ); + + $amqpExchange->expects($this->exactly(2)) + ->method('publish') + ->willReturnOnConsecutiveCalls( + $this->throwException(new \AMQPConnectionException('a socket error occurred')), + null + ); + + $connection = Connection::fromDsn('amqp://localhost', [], $factory); + $connection->publish('body', [], 5000); + } + + public function testItWillRetryMaxThreeTimesWhenAMQPConnectionExceptionIsThrown() + { + $factory = new TestAmqpFactory( + $amqpConnection = $this->createMock(\AMQPConnection::class), + $amqpChannel = $this->createMock(\AMQPChannel::class), + $amqpQueue = $this->createMock(\AMQPQueue::class), + $amqpExchange = $this->createMock(\AMQPExchange::class) + ); + + $exception = new \AMQPConnectionException('a socket error occurred'); + + $amqpExchange->expects($this->exactly(4)) + ->method('publish') + ->willReturnOnConsecutiveCalls( + $this->throwException($exception), + $this->throwException($exception), + $this->throwException($exception), + $this->throwException($exception) + ); + + self::expectException(get_class($exception)); + self::expectExceptionMessage($exception->getMessage()); + + $connection = Connection::fromDsn('amqp://localhost', [], $factory); + $connection->publish('body'); + } + private function createDelayOrRetryConnection(\AMQPExchange $delayExchange, string $deadLetterExchangeName, string $delayQueueName): Connection { $amqpConnection = $this->createMock(\AMQPConnection::class); diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php index 3ea7784d862fd..8689b8ee306cc 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php @@ -306,19 +306,21 @@ public function publish(string $body, array $headers = [], int $delayInMs = 0, ? $this->setupExchangeAndQueues(); // also setup normal exchange for delayed messages so delay queue can DLX messages to it } - if (0 !== $delayInMs) { - $this->publishWithDelay($body, $headers, $delayInMs, $amqpStamp); + $this->withConnectionExceptionRetry(function () use ($body, $headers, $delayInMs, $amqpStamp) { + if (0 !== $delayInMs) { + $this->publishWithDelay($body, $headers, $delayInMs, $amqpStamp); - return; - } + return; + } - $this->publishOnExchange( - $this->exchange(), - $body, - $this->getRoutingKeyForMessage($amqpStamp), - $headers, - $amqpStamp - ); + $this->publishOnExchange( + $this->exchange(), + $body, + $this->getRoutingKeyForMessage($amqpStamp), + $headers, + $amqpStamp + ); + }); } /** @@ -570,13 +572,18 @@ public function exchange(): \AMQPExchange private function clearWhenDisconnected(): void { if (!$this->channel()->isConnected()) { - $this->amqpChannel = null; - $this->amqpQueues = []; - $this->amqpExchange = null; - $this->amqpDelayExchange = null; + $this->clear(); } } + private function clear(): void + { + $this->amqpChannel = null; + $this->amqpQueues = []; + $this->amqpExchange = null; + $this->amqpDelayExchange = null; + } + private function getDefaultPublishRoutingKey(): ?string { return $this->exchangeOptions['default_publish_routing_key'] ?? null; @@ -593,6 +600,25 @@ private function getRoutingKeyForMessage(?AmqpStamp $amqpStamp): ?string { return (null !== $amqpStamp ? $amqpStamp->getRoutingKey() : null) ?? $this->getDefaultPublishRoutingKey(); } + + private function withConnectionExceptionRetry(callable $callable): void + { + $maxRetries = 3; + $retries = 0; + + retry: + try { + $callable(); + } catch (\AMQPConnectionException $e) { + if (++$retries <= $maxRetries) { + $this->clear(); + + goto retry; + } + + throw $e; + } + } } if (!class_exists(\Symfony\Component\Messenger\Transport\AmqpExt\Connection::class, false)) { From e9f4ac93387eeac92183218c5ddf47e571804f2b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 2 Jun 2024 18:00:59 +0200 Subject: [PATCH 04/39] Bump Symfony version to 5.4.41 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index d25647c87d157..0c4a13666d829 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.40'; - public const VERSION_ID = 50440; + public const VERSION = '5.4.41-DEV'; + public const VERSION_ID = 50441; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 40; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 41; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025'; From c655569777557af2e59658d92b560a5aabe6bc64 Mon Sep 17 00:00:00 2001 From: Jakub Podhorsky Date: Thu, 30 May 2024 11:21:38 +0200 Subject: [PATCH 05/39] [String] Fix Inflector for 'hardware' --- src/Symfony/Component/String/Inflector/EnglishInflector.php | 3 +++ .../Component/String/Tests/Inflector/EnglishInflectorTest.php | 1 + 2 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/String/Inflector/EnglishInflector.php b/src/Symfony/Component/String/Inflector/EnglishInflector.php index d9eff19b9a950..4739f07c7be1b 100644 --- a/src/Symfony/Component/String/Inflector/EnglishInflector.php +++ b/src/Symfony/Component/String/Inflector/EnglishInflector.php @@ -399,6 +399,9 @@ final class EnglishInflector implements InflectorInterface // aircraft 'tfarcria', + + // hardware + 'erawdrah', ]; /** diff --git a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php index ba8d6d797c4d0..89f4966a40c1f 100644 --- a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php +++ b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php @@ -302,6 +302,7 @@ public static function pluralizeProvider() ['icon', 'icons'], ['hippocampus', 'hippocampi'], ['campus', 'campuses'], + ['hardware', 'hardware'], // test casing: if the first letter was uppercase, it should remain so ['Man', 'Men'], From c9b117c85b5fa1837e92dbe0d0770843d711b899 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 3 Jun 2024 08:54:18 +0200 Subject: [PATCH 06/39] not registered definitions must not be modified --- .../DependencyInjection/FrameworkExtension.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f7ab7e3ed5835..ebaed7c2b2b76 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1854,6 +1854,10 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->setParameter('serializer.default_context', $defaultContext); } + if (!$container->hasDefinition('serializer.normalizer.object')) { + return; + } + $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); $context = []; From 87b4904ba7945beacf60b07b09cdbc64e7dbacc1 Mon Sep 17 00:00:00 2001 From: Michael Hirschler Date: Tue, 4 Jun 2024 09:06:48 +0200 Subject: [PATCH 07/39] add space in error message --- .../Bundle/SecurityBundle/Security/FirewallAwareTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallAwareTrait.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallAwareTrait.php index d79d0b7a1df53..a04101626c916 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallAwareTrait.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallAwareTrait.php @@ -41,7 +41,7 @@ private function getForFirewall(): object if (!$this->locator->has($firewallName)) { $message = 'No '.$serviceIdentifier.' found for this firewall.'; if (\defined(static::class.'::FIREWALL_OPTION')) { - $message .= sprintf('Did you forget to add a "'.static::FIREWALL_OPTION.'" key under your "%s" firewall?', $firewallName); + $message .= sprintf(' Did you forget to add a "'.static::FIREWALL_OPTION.'" key under your "%s" firewall?', $firewallName); } throw new \LogicException($message); From 10132c921b4d8e353d8a3f402744a7e5f3f4bb2a Mon Sep 17 00:00:00 2001 From: Antoine M Date: Tue, 4 Jun 2024 23:40:07 +0200 Subject: [PATCH 08/39] chore: upgrade class doc --- src/Symfony/Component/HttpKernel/Event/KernelEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Event/KernelEvent.php b/src/Symfony/Component/HttpKernel/Event/KernelEvent.php index d9d425e114b93..87933187a32c7 100644 --- a/src/Symfony/Component/HttpKernel/Event/KernelEvent.php +++ b/src/Symfony/Component/HttpKernel/Event/KernelEvent.php @@ -16,7 +16,7 @@ use Symfony\Contracts\EventDispatcher\Event; /** - * Base class for events thrown in the HttpKernel component. + * Base class for events dispatched in the HttpKernel component. * * @author Bernhard Schussek */ From d35d4a337be7f838520d89abe80788d21e43b35e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 7 Jun 2024 09:46:25 +0200 Subject: [PATCH 09/39] properly handle invalid data for false/true types --- .../Normalizer/AbstractObjectNormalizer.php | 32 +++++++++-- .../AbstractObjectNormalizerTest.php | 57 +++++++++++++++++++ 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 5a51bde39b7ab..63b519b701305 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -621,12 +621,34 @@ private function validateAndDenormalize(array $types, string $currentClass, stri return (float) $data; } - if (Type::BUILTIN_TYPE_FALSE === $builtinType && false === $data) { - return $data; - } + switch ($builtinType) { + case Type::BUILTIN_TYPE_ARRAY: + case Type::BUILTIN_TYPE_BOOL: + case Type::BUILTIN_TYPE_CALLABLE: + case Type::BUILTIN_TYPE_FLOAT: + case Type::BUILTIN_TYPE_INT: + case Type::BUILTIN_TYPE_ITERABLE: + case Type::BUILTIN_TYPE_NULL: + case Type::BUILTIN_TYPE_OBJECT: + case Type::BUILTIN_TYPE_RESOURCE: + case Type::BUILTIN_TYPE_STRING: + if (('is_'.$builtinType)($data)) { + return $data; + } + + break; + case Type::BUILTIN_TYPE_FALSE: + if (false === $data) { + return $data; + } + + break; + case Type::BUILTIN_TYPE_TRUE: + if (true === $data) { + return $data; + } - if (('is_'.$builtinType)($data)) { - return $data; + break; } } catch (NotNormalizableValueException $e) { if (!$isUnionType && !$isNullable) { diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index a6477e97ad331..afaf57ea06b52 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -687,6 +687,26 @@ protected function setAttributeValue(object $object, string $attribute, $value, $this->assertSame('scalar', $normalizer->denormalize('scalar', XmlScalarDummy::class, 'xml')->value); } + + /** + * @dataProvider provideBooleanTypesData + */ + public function testDenormalizeBooleanTypesWithNotMatchingData(array $data, string $type) + { + $normalizer = new AbstractObjectNormalizerWithMetadataAndPropertyTypeExtractors(); + + $this->expectException(NotNormalizableValueException::class); + + $normalizer->denormalize($data, $type); + } + + public function provideBooleanTypesData() + { + return [ + [['foo' => true], FalsePropertyDummy::class], + [['foo' => false], TruePropertyDummy::class], + ]; + } } class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer @@ -816,6 +836,18 @@ class XmlScalarDummy public $value; } +class FalsePropertyDummy +{ + /** @var false */ + public $foo; +} + +class TruePropertyDummy +{ + /** @var true */ + public $foo; +} + class SerializerCollectionDummy implements SerializerInterface, DenormalizerInterface { private $normalizers; @@ -936,3 +968,28 @@ public function __sleep(): array throw new \Error('not serializable'); } } + +class AbstractObjectNormalizerWithMetadataAndPropertyTypeExtractors extends AbstractObjectNormalizer +{ + public function __construct() + { + parent::__construct(new ClassMetadataFactory(new AnnotationLoader()), null, new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()])); + } + + protected function extractAttributes(object $object, ?string $format = null, array $context = []): array + { + return []; + } + + protected function getAttributeValue(object $object, string $attribute, ?string $format = null, array $context = []) + { + return null; + } + + protected function setAttributeValue(object $object, string $attribute, $value, ?string $format = null, array $context = []): void + { + if (property_exists($object, $attribute)) { + $object->$attribute = $value; + } + } +} From 6fb83abcb3a0a89bcb2b0668a8414e7e52a2495a Mon Sep 17 00:00:00 2001 From: Mokhtar Tlili Date: Sat, 8 Jun 2024 16:25:46 +0200 Subject: [PATCH 10/39] fix cssColor HSLA test dataProvider --- .../Validator/Tests/Constraints/CssColorValidatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CssColorValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CssColorValidatorTest.php index 5c7904a8001af..6c298f8236791 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CssColorValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CssColorValidatorTest.php @@ -396,7 +396,7 @@ public static function getInvalidHSL(): array } /** - * @dataProvider getInvalidHSL + * @dataProvider getInvalidHSLA */ public function testInvalidHSLA($cssColor) { From 0d441bf62aa318419ed951c60bd0e32f6339b1c2 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Tue, 7 May 2024 11:00:46 +0200 Subject: [PATCH 11/39] [Messenger] Comply with Amazon SQS requirements for message body --- .../Tests/Transport/AmazonSqsSenderTest.php | 15 +++++++++++++++ .../AmazonSqs/Transport/AmazonSqsSender.php | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php index 80840c859cb05..d11a5d8037b27 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsSenderTest.php @@ -72,4 +72,19 @@ public function testSendWithAmazonSqsXrayTraceHeaderStamp() $sender = new AmazonSqsSender($connection, $serializer); $sender->send($envelope); } + + public function testSendEncodeBodyToRespectAmazonRequirements() + { + $envelope = new Envelope(new DummyMessage('Oy')); + $encoded = ['body' => "\x7", 'headers' => ['type' => DummyMessage::class]]; + + $connection = $this->createMock(Connection::class); + $connection->expects($this->once())->method('send')->with(base64_encode($encoded['body']), $encoded['headers']); + + $serializer = $this->createMock(SerializerInterface::class); + $serializer->method('encode')->with($envelope)->willReturn($encoded); + + $sender = new AmazonSqsSender($connection, $serializer); + $sender->send($envelope); + } } diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsSender.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsSender.php index 1994313720e0d..b253c82e97e30 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsSender.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/AmazonSqsSender.php @@ -38,6 +38,7 @@ public function __construct(Connection $connection, SerializerInterface $seriali public function send(Envelope $envelope): Envelope { $encodedMessage = $this->serializer->encode($envelope); + $encodedMessage = $this->complyWithAmazonSqsRequirements($encodedMessage); /** @var DelayStamp|null $delayStamp */ $delayStamp = $envelope->last(DelayStamp::class); @@ -75,4 +76,20 @@ public function send(Envelope $envelope): Envelope return $envelope; } + + /** + * @see https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html + * + * @param array{body: string, headers?: array} $encodedMessage + * + * @return array{body: string, headers?: array} + */ + private function complyWithAmazonSqsRequirements(array $encodedMessage): array + { + if (preg_match('/[^\x20-\x{D7FF}\xA\xD\x9\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', $encodedMessage['body'])) { + $encodedMessage['body'] = base64_encode($encodedMessage['body']); + } + + return $encodedMessage; + } } From 8ef75c2c012210d7ed88be5953a074fc428b6608 Mon Sep 17 00:00:00 2001 From: seho-nl <65092701+seho-nl@users.noreply.github.com> Date: Tue, 28 May 2024 19:55:02 +0200 Subject: [PATCH 12/39] [Validator] [UniqueValidator] Use correct variable as parameter in (custom) error message --- .../Validator/Constraints/UniqueValidator.php | 2 +- .../Tests/Constraints/UniqueValidatorTest.php | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/UniqueValidator.php b/src/Symfony/Component/Validator/Constraints/UniqueValidator.php index 2758a3faa11f6..95dc48c632186 100644 --- a/src/Symfony/Component/Validator/Constraints/UniqueValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UniqueValidator.php @@ -45,7 +45,7 @@ public function validate($value, Constraint $constraint) if (\in_array($element, $collectionElements, true)) { $this->context->buildViolation($constraint->message) - ->setParameter('{{ value }}', $this->formatValue($value)) + ->setParameter('{{ value }}', $this->formatValue($element)) ->setCode(Unique::IS_NOT_UNIQUE) ->addViolation(); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php index 417050bd8e67d..de0b47280190a 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php @@ -59,7 +59,7 @@ public static function getValidValues() /** * @dataProvider getInvalidValues */ - public function testInvalidValues($value) + public function testInvalidValues($value, $expectedMessageParam) { $constraint = new Unique([ 'message' => 'myMessage', @@ -67,7 +67,7 @@ public function testInvalidValues($value) $this->validator->validate($value, $constraint); $this->buildViolation('myMessage') - ->setParameter('{{ value }}', 'array') + ->setParameter('{{ value }}', $expectedMessageParam) ->setCode(Unique::IS_NOT_UNIQUE) ->assertRaised(); } @@ -77,12 +77,12 @@ public static function getInvalidValues() $object = new \stdClass(); return [ - yield 'not unique booleans' => [[true, true]], - yield 'not unique integers' => [[1, 2, 3, 3]], - yield 'not unique floats' => [[0.1, 0.2, 0.1]], - yield 'not unique string' => [['a', 'b', 'a']], - yield 'not unique arrays' => [[[1, 1], [2, 3], [1, 1]]], - yield 'not unique objects' => [[$object, $object]], + yield 'not unique booleans' => [[true, true], 'true'], + yield 'not unique integers' => [[1, 2, 3, 3], 3], + yield 'not unique floats' => [[0.1, 0.2, 0.1], 0.1], + yield 'not unique string' => [['a', 'b', 'a'], '"a"'], + yield 'not unique arrays' => [[[1, 1], [2, 3], [1, 1]], 'array'], + yield 'not unique objects' => [[$object, $object], 'object'], ]; } @@ -95,7 +95,7 @@ public function testInvalidValueNamed() $this->validator->validate([1, 2, 3, 3], $constraint); $this->buildViolation('myMessage') - ->setParameter('{{ value }}', 'array') + ->setParameter('{{ value }}', '3') ->setCode(Unique::IS_NOT_UNIQUE) ->assertRaised(); } @@ -176,7 +176,7 @@ public function testExpectsInvalidNonStrictComparison() ])); $this->buildViolation('myMessage') - ->setParameter('{{ value }}', 'array') + ->setParameter('{{ value }}', '1') ->setCode(Unique::IS_NOT_UNIQUE) ->assertRaised(); } @@ -206,7 +206,7 @@ public function testExpectsInvalidCaseInsensitiveComparison() ])); $this->buildViolation('myMessage') - ->setParameter('{{ value }}', 'array') + ->setParameter('{{ value }}', '"hello"') ->setCode(Unique::IS_NOT_UNIQUE) ->assertRaised(); } From 91325ea6dd75730874f0c4dce0f2f30ade55b193 Mon Sep 17 00:00:00 2001 From: Geordie Date: Wed, 17 Apr 2024 12:33:44 +0200 Subject: [PATCH 13/39] [String] Fix #54611 pluralization of -on ending words + singularization of -a ending foreign words --- .../Inflector/Tests/InflectorTest.php | 27 ++++++--- src/Symfony/Component/Inflector/composer.json | 2 +- .../String/Inflector/EnglishInflector.php | 59 +++++++++++-------- .../Tests/Inflector/EnglishInflectorTest.php | 28 ++++++--- 4 files changed, 76 insertions(+), 40 deletions(-) diff --git a/src/Symfony/Component/Inflector/Tests/InflectorTest.php b/src/Symfony/Component/Inflector/Tests/InflectorTest.php index 0702c717e3495..d637e3d72d1eb 100644 --- a/src/Symfony/Component/Inflector/Tests/InflectorTest.php +++ b/src/Symfony/Component/Inflector/Tests/InflectorTest.php @@ -37,7 +37,7 @@ public static function singularizeProvider() ['atlases', ['atlas', 'atlase', 'atlasis']], ['axes', ['ax', 'axe', 'axis']], ['babies', 'baby'], - ['bacteria', ['bacterion', 'bacterium']], + ['bacteria', 'bacterium'], ['bases', ['bas', 'base', 'basis']], ['batches', ['batch', 'batche']], ['beaux', 'beau'], @@ -48,6 +48,7 @@ public static function singularizeProvider() ['bureaux', 'bureau'], ['buses', ['bus', 'buse', 'busis']], ['bushes', ['bush', 'bushe']], + ['buttons', 'button'], ['calves', ['calf', 'calve', 'calff']], ['cars', 'car'], ['cassettes', ['cassett', 'cassette']], @@ -58,10 +59,12 @@ public static function singularizeProvider() ['circuses', ['circus', 'circuse', 'circusis']], ['cliffs', 'cliff'], ['committee', 'committee'], + ['corpora', 'corpus'], + ['coupons', 'coupon'], ['crises', ['cris', 'crise', 'crisis']], - ['criteria', ['criterion', 'criterium']], + ['criteria', 'criterion'], ['cups', 'cup'], - ['coupons', 'coupon'], + ['curricula', 'curriculum'], ['data', 'data'], ['days', 'day'], ['discos', 'disco'], @@ -87,6 +90,7 @@ public static function singularizeProvider() ['funguses', ['fungus', 'funguse', 'fungusis']], ['garages', ['garag', 'garage']], ['geese', 'goose'], + ['genera', 'genus'], ['halves', ['half', 'halve', 'halff']], ['hats', 'hat'], ['heroes', ['hero', 'heroe']], @@ -107,6 +111,8 @@ public static function singularizeProvider() ['lives', 'life'], ['matrices', ['matrex', 'matrix', 'matrice']], ['matrixes', 'matrix'], + ['media', 'medium'], + ['memoranda', 'memorandum'], ['men', 'man'], ['mice', 'mouse'], ['moves', 'move'], @@ -120,7 +126,7 @@ public static function singularizeProvider() ['parties', 'party'], ['people', 'person'], ['persons', 'person'], - ['phenomena', ['phenomenon', 'phenomenum']], + ['phenomena', 'phenomenon'], ['photos', 'photo'], ['pianos', 'piano'], ['plateaux', 'plateau'], @@ -144,7 +150,7 @@ public static function singularizeProvider() ['spies', 'spy'], ['staves', ['staf', 'stave', 'staff']], ['stories', 'story'], - ['strata', ['straton', 'stratum']], + ['strata', 'stratum'], ['suitcases', ['suitcas', 'suitcase', 'suitcasis']], ['syllabi', 'syllabus'], ['tags', 'tag'], @@ -195,7 +201,9 @@ public static function pluralizeProvider() ['bureau', ['bureaus', 'bureaux']], ['bus', 'buses'], ['bush', 'bushes'], + ['button', 'buttons'], ['calf', ['calfs', 'calves']], + ['campus', 'campuses'], ['car', 'cars'], ['cassette', 'cassettes'], ['cave', 'caves'], @@ -205,10 +213,11 @@ public static function pluralizeProvider() ['circus', 'circuses'], ['cliff', 'cliffs'], ['committee', 'committees'], + ['coupon', 'coupons'], ['crisis', 'crises'], - ['criteria', 'criterion'], + ['criterion', 'criteria'], ['cup', 'cups'], - ['coupon', 'coupons'], + ['curriculum', 'curricula'], ['data', 'data'], ['day', 'days'], ['disco', 'discos'], @@ -232,10 +241,12 @@ public static function pluralizeProvider() ['half', ['halfs', 'halves']], ['hat', 'hats'], ['hero', 'heroes'], + ['hippocampus', 'hippocampi'], ['hippopotamus', 'hippopotami'], // hippopotamuses ['hoax', 'hoaxes'], ['hoof', ['hoofs', 'hooves']], ['house', 'houses'], + ['icon', 'icons'], ['index', ['indicies', 'indexes']], ['ion', 'ions'], ['iris', 'irises'], @@ -248,6 +259,8 @@ public static function pluralizeProvider() ['louse', 'lice'], ['man', 'men'], ['matrix', ['matricies', 'matrixes']], + ['medium', 'media'], + ['memorandum', 'memoranda'], ['mouse', 'mice'], ['move', 'moves'], ['movie', 'movies'], diff --git a/src/Symfony/Component/Inflector/composer.json b/src/Symfony/Component/Inflector/composer.json index 5b7280c1f42ce..6b46f7cb918b1 100644 --- a/src/Symfony/Component/Inflector/composer.json +++ b/src/Symfony/Component/Inflector/composer.json @@ -26,7 +26,7 @@ "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-php80": "^1.16", - "symfony/string": "^5.3.10|^6.0" + "symfony/string": "^5.4.41|^6.4.9" }, "autoload": { "psr-4": { "Symfony\\Component\\Inflector\\": "" }, diff --git a/src/Symfony/Component/String/Inflector/EnglishInflector.php b/src/Symfony/Component/String/Inflector/EnglishInflector.php index 4739f07c7be1b..e068fcbcd6d98 100644 --- a/src/Symfony/Component/String/Inflector/EnglishInflector.php +++ b/src/Symfony/Component/String/Inflector/EnglishInflector.php @@ -25,8 +25,32 @@ final class EnglishInflector implements InflectorInterface // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: singular suffix, normal - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) - ['a', 1, true, true, ['on', 'um']], + // bacteria (bacterium) + ['airetcab', 8, true, true, 'bacterium'], + + // corpora (corpus) + ['aroproc', 7, true, true, 'corpus'], + + // criteria (criterion) + ['airetirc', 8, true, true, 'criterion'], + + // curricula (curriculum) + ['alucirruc', 9, true, true, 'curriculum'], + + // genera (genus) + ['areneg', 6, true, true, 'genus'], + + // media (medium) + ['aidem', 5, true, true, 'medium'], + + // memoranda (memorandum) + ['adnaromem', 9, true, true, 'memorandum'], + + // phenomena (phenomenon) + ['anemonehp', 9, true, true, 'phenomenon'], + + // strata (stratum) + ['atarts', 6, true, true, 'stratum'], // nebulae (nebula) ['ea', 2, true, true, 'a'], @@ -141,7 +165,7 @@ final class EnglishInflector implements InflectorInterface // shoes (shoe) ['se', 2, true, true, ['', 'e']], - // status (status) + // status (status) ['sutats', 6, true, true, 'status'], // tags (tag) @@ -241,7 +265,7 @@ final class EnglishInflector implements InflectorInterface // albums (album) ['mubla', 5, true, true, 'albums'], - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) + // bacteria (bacterium), curricula (curriculum), media (medium), memoranda (memorandum), phenomena (phenomenon), strata (stratum) ['mu', 2, true, true, 'a'], // men (man), women (woman) @@ -250,20 +274,11 @@ final class EnglishInflector implements InflectorInterface // people (person) ['nosrep', 6, true, true, ['persons', 'people']], - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) - ['noi', 3, true, true, 'ions'], - - // coupon (coupons) - ['nop', 3, true, true, 'pons'], - - // seasons (season), treasons (treason), poisons (poison), lessons (lesson) - ['nos', 3, true, true, 'sons'], - - // icons (icon) - ['noc', 3, true, true, 'cons'], + // criteria (criterion) + ['noiretirc', 9, true, true, 'criteria'], - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) - ['no', 2, true, true, 'a'], + // phenomena (phenomenon) + ['nonemonehp', 10, true, true, 'phenomena'], // echoes (echo) ['ohce', 4, true, true, 'echoes'], @@ -404,9 +419,6 @@ final class EnglishInflector implements InflectorInterface 'erawdrah', ]; - /** - * {@inheritdoc} - */ public function singularize(string $plural): array { $pluralRev = strrev($plural); @@ -438,7 +450,7 @@ public function singularize(string $plural): array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $pluralLength) { - $nextIsVowel = false !== strpos('aeiou', $lowerPluralRev[$j]); + $nextIsVowel = str_contains('aeiou', $lowerPluralRev[$j]); if (!$map[2] && $nextIsVowel) { // suffix may not succeed a vowel but next char is one @@ -483,9 +495,6 @@ public function singularize(string $plural): array return [$plural]; } - /** - * {@inheritdoc} - */ public function pluralize(string $singular): array { $singularRev = strrev($singular); @@ -518,7 +527,7 @@ public function pluralize(string $singular): array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $singularLength) { - $nextIsVowel = false !== strpos('aeiou', $lowerSingularRev[$j]); + $nextIsVowel = str_contains('aeiou', $lowerSingularRev[$j]); if (!$map[2] && $nextIsVowel) { // suffix may not succeed a vowel but next char is one diff --git a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php index 89f4966a40c1f..6744814b66603 100644 --- a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php +++ b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php @@ -35,7 +35,7 @@ public static function singularizeProvider() ['atlases', ['atlas', 'atlase', 'atlasis']], ['axes', ['ax', 'axe', 'axis']], ['babies', 'baby'], - ['bacteria', ['bacterion', 'bacterium']], + ['bacteria', 'bacterium'], ['bases', ['bas', 'base', 'basis']], ['batches', ['batch', 'batche']], ['beaux', 'beau'], @@ -46,6 +46,7 @@ public static function singularizeProvider() ['bureaux', 'bureau'], ['buses', ['bus', 'buse', 'busis']], ['bushes', ['bush', 'bushe']], + ['buttons', 'button'], ['calves', ['calf', 'calve', 'calff']], ['cars', 'car'], ['cassettes', ['cassett', 'cassette']], @@ -57,10 +58,12 @@ public static function singularizeProvider() ['cliffs', 'cliff'], ['codes', 'code'], ['committee', 'committee'], + ['corpora', 'corpus'], + ['coupons', 'coupon'], ['crises', ['cris', 'crise', 'crisis']], - ['criteria', ['criterion', 'criterium']], + ['criteria', 'criterion'], ['cups', 'cup'], - ['coupons', 'coupon'], + ['curricula', 'curriculum'], ['data', 'data'], ['days', 'day'], ['discos', 'disco'], @@ -86,6 +89,7 @@ public static function singularizeProvider() ['funguses', ['fungus', 'funguse', 'fungusis']], ['garages', ['garag', 'garage']], ['geese', 'goose'], + ['genera', 'genus'], ['halves', ['half', 'halve', 'halff']], ['hats', 'hat'], ['heroes', ['hero', 'heroe']], @@ -106,6 +110,8 @@ public static function singularizeProvider() ['lives', 'life'], ['matrices', ['matrex', 'matrix', 'matrice']], ['matrixes', 'matrix'], + ['media', 'medium'], + ['memoranda', 'memorandum'], ['men', 'man'], ['mice', 'mouse'], ['moves', 'move'], @@ -120,7 +126,7 @@ public static function singularizeProvider() ['parties', 'party'], ['people', 'person'], ['persons', 'person'], - ['phenomena', ['phenomenon', 'phenomenum']], + ['phenomena', 'phenomenon'], ['photos', 'photo'], ['pianos', 'piano'], ['plateaux', 'plateau'], @@ -146,7 +152,7 @@ public static function singularizeProvider() ['status', 'status'], ['statuses', 'status'], ['stories', 'story'], - ['strata', ['straton', 'stratum']], + ['strata', 'stratum'], ['suitcases', ['suitcas', 'suitcase', 'suitcasis']], ['syllabi', 'syllabus'], ['tags', 'tag'], @@ -200,7 +206,9 @@ public static function pluralizeProvider() ['bureau', ['bureaus', 'bureaux']], ['bus', 'buses'], ['bush', 'bushes'], + ['button', 'buttons'], ['calf', ['calfs', 'calves']], + ['campus', 'campuses'], ['car', 'cars'], ['cassette', 'cassettes'], ['cave', 'caves'], @@ -210,10 +218,11 @@ public static function pluralizeProvider() ['circus', 'circuses'], ['cliff', 'cliffs'], ['committee', 'committees'], + ['coupon', 'coupons'], ['crisis', 'crises'], - ['criteria', 'criterion'], + ['criterion', 'criteria'], ['cup', 'cups'], - ['coupon', 'coupons'], + ['curriculum', 'curricula'], ['data', 'data'], ['day', 'days'], ['disco', 'discos'], @@ -237,10 +246,12 @@ public static function pluralizeProvider() ['half', ['halfs', 'halves']], ['hat', 'hats'], ['hero', 'heroes'], + ['hippocampus', 'hippocampi'], ['hippopotamus', 'hippopotami'], // hippopotamuses ['hoax', 'hoaxes'], ['hoof', ['hoofs', 'hooves']], ['house', 'houses'], + ['icon', 'icons'], ['index', ['indicies', 'indexes']], ['ion', 'ions'], ['iris', 'irises'], @@ -253,6 +264,8 @@ public static function pluralizeProvider() ['louse', 'lice'], ['man', 'men'], ['matrix', ['matricies', 'matrixes']], + ['medium', 'media'], + ['memorandum', 'memoranda'], ['mouse', 'mice'], ['move', 'moves'], ['movie', 'movies'], @@ -286,6 +299,7 @@ public static function pluralizeProvider() ['shoe', 'shoes'], ['species', 'species'], ['status', ['status', 'statuses']], + ['stratum', 'strata'], ['spy', 'spies'], ['staff', 'staves'], ['story', 'stories'], From 2b46e2a6527bc1348d684a29335d6a75f0006eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tinjo=20Sch=C3=B6ni?= <32767367+tscni@users.noreply.github.com> Date: Sun, 9 Jun 2024 20:42:34 +0200 Subject: [PATCH 14/39] [ErrorHandler] Fix rendered exception code highlighting on PHP 8.3 --- src/Symfony/Bridge/Twig/Extension/CodeExtension.php | 8 +++----- .../ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php | 8 +++----- .../ErrorHandler/Resources/assets/css/exception.css | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index d76924633efe0..e7a3329478d98 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -129,12 +129,10 @@ public function fileExcerpt(string $file, int $line, int $srcContext = 3): ?stri if (\PHP_VERSION_ID >= 80300) { // remove main pre/code tags $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline code tags - $code = preg_replace_callback('#]++)>((?:[^<]*+\\n)++[^<]*+)#', function ($m) { - return "".str_replace("\n", "\n", $m[2]).''; + // split multiline span tags + $code = preg_replace_callback('#]++)>((?:[^<\\n]*+\\n)++[^<]*+)#', function ($m) { + return "".str_replace("\n", "\n", $m[2]).''; }, $code); - // Convert spaces to html entities to preserve indentation when rendered - $code = str_replace(' ', ' ', $code); $content = explode("\n", $code); } else { // remove main code/span tags diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php index 5b264fa5a7e90..05cbeec166b6e 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php +++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php @@ -274,12 +274,10 @@ private function fileExcerpt(string $file, int $line, int $srcContext = 3): stri if (\PHP_VERSION_ID >= 80300) { // remove main pre/code tags $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline code tags - $code = preg_replace_callback('#]++)>((?:[^<]*+\\n)++[^<]*+)#', function ($m) { - return "".str_replace("\n", "\n", $m[2]).''; + // split multiline span tags + $code = preg_replace_callback('#]++)>((?:[^<\\n]*+\\n)++[^<]*+)#', function ($m) { + return "".str_replace("\n", "\n", $m[2]).''; }, $code); - // Convert spaces to html entities to preserve indentation when rendered - $code = str_replace(' ', ' ', $code); $content = explode("\n", $code); } else { // remove main code/span tags diff --git a/src/Symfony/Component/ErrorHandler/Resources/assets/css/exception.css b/src/Symfony/Component/ErrorHandler/Resources/assets/css/exception.css index 7cb3206da2055..2d05a5e6a6620 100644 --- a/src/Symfony/Component/ErrorHandler/Resources/assets/css/exception.css +++ b/src/Symfony/Component/ErrorHandler/Resources/assets/css/exception.css @@ -242,7 +242,7 @@ header .container { display: flex; justify-content: space-between; } .trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } .trace-code li + li { margin-top: 5px; } .trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; } -.trace-code li code { color: var(--base-6); white-space: nowrap; } +.trace-code li code { color: var(--base-6); white-space: pre; } .trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } From 69d3d7593e585c39a7d2a087586dd8bab98928b0 Mon Sep 17 00:00:00 2001 From: Cosmin Sandu Date: Mon, 10 Jun 2024 12:18:21 +0300 Subject: [PATCH 15/39] [57251] Missing translations for Romanian (ro) --- .../Validator/Resources/translations/validators.ro.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf index 3d0b819a95441..3c0ace5490efd 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf @@ -440,7 +440,7 @@ This URL is missing a top-level domain. - Acest URL îi lipsește un domeniu de nivel superior. + Acestui URL îi lipsește un domeniu de nivel superior. From f903893dff5a0f18c9069ee4fc90466dfd60a9af Mon Sep 17 00:00:00 2001 From: HypeMC Date: Fri, 31 May 2024 18:43:25 +0200 Subject: [PATCH 16/39] [FrameworkBundle] Fix setting default context for certain normalizers --- .../FrameworkExtension.php | 8 ++- .../Resources/config/serializer.php | 1 - .../Tests/Functional/AbstractWebTestCase.php | 2 +- .../Tests/Functional/SerializerTest.php | 70 ++++++++++++------- .../Tests/Functional/app/AppKernel.php | 5 ++ .../Functional/app/Serializer/config.yml | 45 ------------ .../app/Serializer/default_context.yaml | 59 ++++++++++++++++ 7 files changed, 115 insertions(+), 75 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/default_context.yaml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ebaed7c2b2b76..71505f2519340 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1859,18 +1859,20 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder } $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = []; + $context = $arguments[6] ?? $defaultContext; if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { - $context += ($arguments[6] ?? $defaultContext) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; + $context += ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); } if ($config['max_depth_handler'] ?? false) { - $context += ($arguments[6] ?? $defaultContext) + ['max_depth_handler' => new Reference($config['max_depth_handler'])]; + $context += ['max_depth_handler' => new Reference($config['max_depth_handler'])]; } $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); + + $container->getDefinition('serializer.normalizer.property')->setArgument(5, $defaultContext); } private function registerPropertyInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php index 7762e5a64ca86..2fb42027fd61e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php @@ -139,7 +139,6 @@ service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, - [], ]) ->alias(PropertyNormalizer::class, 'serializer.normalizer.property') diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php index bce53b8668251..30ca91d1ee5b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php @@ -52,7 +52,7 @@ protected static function getKernelClass(): string protected static function createKernel(array $options = []): KernelInterface { - $class = self::getKernelClass(); + $class = static::getKernelClass(); if (!isset($options['test_case'])) { throw new \InvalidArgumentException('The option "test_case" must be set.'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php index 9a6527b14dd62..7ce9b0735e134 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SerializerTest.php @@ -11,6 +11,10 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\AppKernel; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + /** * @author Kévin Dunglas */ @@ -33,39 +37,55 @@ public function testDeserializeArrayOfObject() $this->assertEquals($expected, $result); } - /** - * @dataProvider provideNormalizersAndEncodersWithDefaultContextOption - */ - public function testNormalizersAndEncodersUseDefaultContextConfigOption(string $normalizerId) + public function testNormalizersAndEncodersUseDefaultContextConfigOption() { - static::bootKernel(['test_case' => 'Serializer']); + /** @var SerializerKernel $kernel */ + $kernel = static::bootKernel(['test_case' => 'Serializer', 'root_config' => 'default_context.yaml']); + + foreach ($kernel->normalizersAndEncoders as $normalizerOrEncoderId) { + $normalizerOrEncoder = static::getContainer()->get($normalizerOrEncoderId); - $normalizer = static::getContainer()->get($normalizerId); + $reflectionObject = new \ReflectionObject($normalizerOrEncoder); + $property = $reflectionObject->getProperty('defaultContext'); + $property->setAccessible(true); - $reflectionObject = new \ReflectionObject($normalizer); - $property = $reflectionObject->getProperty('defaultContext'); - $property->setAccessible(true); + $defaultContext = $property->getValue($normalizerOrEncoder); - $defaultContext = $property->getValue($normalizer); + self::assertArrayHasKey('fake_context_option', $defaultContext); + self::assertEquals('foo', $defaultContext['fake_context_option']); + } + } - self::assertArrayHasKey('fake_context_option', $defaultContext); - self::assertEquals('foo', $defaultContext['fake_context_option']); + protected static function getKernelClass(): string + { + return SerializerKernel::class; } +} + +class SerializerKernel extends AppKernel implements CompilerPassInterface +{ + public $normalizersAndEncoders = [ + 'serializer.normalizer.property.alias', // Special case as this normalizer isn't tagged + ]; - public static function provideNormalizersAndEncodersWithDefaultContextOption(): array + public function process(ContainerBuilder $container) { - return [ - ['serializer.normalizer.constraint_violation_list.alias'], - ['serializer.normalizer.dateinterval.alias'], - ['serializer.normalizer.datetime.alias'], - ['serializer.normalizer.json_serializable.alias'], - ['serializer.normalizer.problem.alias'], - ['serializer.normalizer.uid.alias'], - ['serializer.normalizer.object.alias'], - ['serializer.encoder.xml.alias'], - ['serializer.encoder.yaml.alias'], - ['serializer.encoder.csv.alias'], - ]; + $services = array_merge( + $container->findTaggedServiceIds('serializer.normalizer'), + $container->findTaggedServiceIds('serializer.encoder') + ); + foreach ($services as $serviceId => $attributes) { + $class = $container->getDefinition($serviceId)->getClass(); + if (null === $reflectionConstructor = (new \ReflectionClass($class))->getConstructor()) { + continue; + } + foreach ($reflectionConstructor->getParameters() as $reflectionParam) { + if ('array $defaultContext' === $reflectionParam->getType()->getName().' $'.$reflectionParam->getName()) { + $this->normalizersAndEncoders[] = $serviceId.'.alias'; + break; + } + } + } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php index 49fb0ca2e6f8d..0c3c9cc3564e4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php @@ -49,6 +49,11 @@ public function __construct($varDir, $testCase, $rootConfig, $environment, $debu parent::__construct($environment, $debug); } + protected function getContainerClass(): string + { + return parent::getContainerClass().substr(md5($this->rootConfig), -16); + } + public function registerBundles(): iterable { if (!file_exists($filename = $this->getProjectDir().'/'.$this->testCase.'/bundles.php')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml index f023f6341970d..c22edfccef331 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml @@ -8,7 +8,6 @@ framework: max_depth_handler: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Serializer\MaxDepthHandler default_context: enable_max_depth: true - fake_context_option: foo property_info: { enabled: true } services: @@ -16,50 +15,6 @@ services: alias: serializer public: true - serializer.normalizer.constraint_violation_list.alias: - alias: serializer.normalizer.constraint_violation_list - public: true - - serializer.normalizer.dateinterval.alias: - alias: serializer.normalizer.dateinterval - public: true - - serializer.normalizer.datetime.alias: - alias: serializer.normalizer.datetime - public: true - - serializer.normalizer.json_serializable.alias: - alias: serializer.normalizer.json_serializable - public: true - - serializer.normalizer.problem.alias: - alias: serializer.normalizer.problem - public: true - - serializer.normalizer.uid.alias: - alias: serializer.normalizer.uid - public: true - - serializer.normalizer.property.alias: - alias: serializer.normalizer.property - public: true - - serializer.normalizer.object.alias: - alias: serializer.normalizer.object - public: true - - serializer.encoder.xml.alias: - alias: serializer.encoder.xml - public: true - - serializer.encoder.yaml.alias: - alias: serializer.encoder.yaml - public: true - - serializer.encoder.csv.alias: - alias: serializer.encoder.csv - public: true - Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Serializer\CircularReferenceHandler: ~ Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Serializer\MaxDepthHandler: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/default_context.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/default_context.yaml new file mode 100644 index 0000000000000..de6114c5d4bb8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/default_context.yaml @@ -0,0 +1,59 @@ +imports: + - { resource: ../config/default.yml } + +framework: + serializer: + enabled: true + circular_reference_handler: ~ # This must be null + max_depth_handler: ~ # This must be null + default_context: + fake_context_option: foo + +services: + serializer.normalizer.constraint_violation_list.alias: + alias: serializer.normalizer.constraint_violation_list + public: true + + serializer.normalizer.dateinterval.alias: + alias: serializer.normalizer.dateinterval + public: true + + serializer.normalizer.datetime.alias: + alias: serializer.normalizer.datetime + public: true + + serializer.normalizer.json_serializable.alias: + alias: serializer.normalizer.json_serializable + public: true + + serializer.normalizer.object.alias: + alias: serializer.normalizer.object + public: true + + serializer.normalizer.problem.alias: + alias: serializer.normalizer.problem + public: true + + serializer.normalizer.property.alias: + alias: serializer.normalizer.property + public: true + + serializer.normalizer.uid.alias: + alias: serializer.normalizer.uid + public: true + + serializer.encoder.csv.alias: + alias: serializer.encoder.csv + public: true + + serializer.encoder.json.alias: + alias: serializer.encoder.json + public: true + + serializer.encoder.xml.alias: + alias: serializer.encoder.xml + public: true + + serializer.encoder.yaml.alias: + alias: serializer.encoder.yaml + public: true From 661e79a581f3c4cf564676c27fdce7ae81f08a6a Mon Sep 17 00:00:00 2001 From: HypeMC Date: Fri, 14 Jun 2024 21:09:16 +0200 Subject: [PATCH 17/39] [PhpUnitBridge] Add missing import --- src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 95312e2b3ce80..2821d92e358f4 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\PhpUnit; +use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestResult; use PHPUnit\Runner\ErrorHandler; use PHPUnit\Util\Error\Handler; From 5f68cf780fcd4013c2cacc760a5368dabdc1f543 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 15 Jun 2024 00:34:59 +0200 Subject: [PATCH 18/39] test handling of special "value" constraint option --- .../Tests/Validator/Constraints/UniqueEntityTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php index 2c9c3815654ba..5d9edce2408c2 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityTest.php @@ -63,6 +63,13 @@ public function testAttributeWithGroupsAndPaylod() self::assertSame('some attached data', $constraint->payload); self::assertSame(['some_group'], $constraint->groups); } + + public function testValueOptionConfiguresFields() + { + $constraint = new UniqueEntity(['value' => 'email']); + + $this->assertSame('email', $constraint->fields); + } } #[UniqueEntity(['email'], message: 'myMessage')] From 3857545d33cd97f4eb85d9fae9ea8681e4201f81 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Mon, 27 May 2024 01:34:50 +0200 Subject: [PATCH 19/39] [Serializer] Fix `ObjectNormalizer` with property path --- .../Normalizer/ObjectNormalizer.php | 6 +++- .../Tests/Fixtures/property-path-mapping.yaml | 5 +++ .../Tests/Normalizer/ObjectNormalizerTest.php | 35 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/property-path-mapping.yaml diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index 6a5413f69d317..f4a234981e6fb 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -194,7 +194,11 @@ protected function isAllowedAttribute($classOrObject, string $attribute, ?string $class = \is_object($classOrObject) ? \get_class($classOrObject) : $classOrObject; if ($context['_read_attributes'] ?? true) { - return $this->propertyInfoExtractor->isReadable($class, $attribute) || $this->hasAttributeAccessorMethod($class, $attribute); + return (\is_object($classOrObject) && $this->propertyAccessor->isReadable($classOrObject, $attribute)) || $this->propertyInfoExtractor->isReadable($class, $attribute) || $this->hasAttributeAccessorMethod($class, $attribute); + } + + if (str_contains($attribute, '.')) { + return true; } if ($this->propertyInfoExtractor->isWritable($class, $attribute)) { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/property-path-mapping.yaml b/src/Symfony/Component/Serializer/Tests/Fixtures/property-path-mapping.yaml new file mode 100644 index 0000000000000..834b39150fe89 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/property-path-mapping.yaml @@ -0,0 +1,5 @@ +Symfony\Component\Serializer\Tests\Normalizer\ObjectOuter: + attributes: + inner.foo: + serialized_name: inner_foo + groups: [ 'read' ] diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 5f88844974cd9..4ff8c114db058 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -25,6 +25,7 @@ use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; +use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; use Symfony\Component\Serializer\NameConverter\AdvancedNameConverterInterface; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter; @@ -911,6 +912,40 @@ public function testDenormalizeWithIgnoreAnnotationAndPrivateProperties() $this->assertEquals($expected, $obj); } + + public function testNormalizeWithPropertyPath() + { + $classMetadataFactory = new ClassMetadataFactory(new YamlFileLoader(__DIR__.'/../Fixtures/property-path-mapping.yaml')); + $normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory)); + + $dummyInner = new ObjectInner(); + $dummyInner->foo = 'foo'; + $dummy = new ObjectOuter(); + $dummy->setInner($dummyInner); + + $this->assertSame(['inner_foo' => 'foo'], $normalizer->normalize($dummy, 'json', ['groups' => 'read'])); + } + + public function testDenormalizeWithPropertyPath() + { + $classMetadataFactory = new ClassMetadataFactory(new YamlFileLoader(__DIR__.'/../Fixtures/property-path-mapping.yaml')); + $normalizer = new ObjectNormalizer($classMetadataFactory, new MetadataAwareNameConverter($classMetadataFactory)); + + $dummy = new ObjectOuter(); + $dummy->setInner(new ObjectInner()); + + $obj = $normalizer->denormalize(['inner_foo' => 'foo'], ObjectOuter::class, 'json', [ + 'object_to_populate' => $dummy, + 'groups' => 'read', + ]); + + $expectedInner = new ObjectInner(); + $expectedInner->foo = 'foo'; + $expected = new ObjectOuter(); + $expected->setInner($expectedInner); + + $this->assertEquals($expected, $obj); + } } class ProxyObjectDummy extends ObjectDummy From 40341a1f6dd2e0387b6f3da32b1492a339123525 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Tue, 11 Jun 2024 17:49:33 +0200 Subject: [PATCH 20/39] [HttpKernel][Security] Fix accessing session for stateless request --- .../HttpKernel/DataCollector/RequestDataCollector.php | 2 +- .../Component/HttpKernel/EventListener/ProfilerListener.php | 2 +- .../HttpKernel/Tests/EventListener/ProfilerListenerTest.php | 4 ++-- .../Component/Security/Http/Firewall/ContextListener.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php index 6931336f06d17..2a4392aa8c340 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php @@ -66,7 +66,7 @@ public function collect(Request $request, Response $response, ?\Throwable $excep $sessionMetadata = []; $sessionAttributes = []; $flashes = []; - if ($request->hasSession()) { + if (!$request->attributes->getBoolean('_stateless') && $request->hasSession()) { $session = $request->getSession(); if ($session->isStarted()) { $sessionMetadata['Created'] = date(\DATE_RFC822, $session->getMetadataBag()->getCreated()); diff --git a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php index e4261871b0e72..c7950b8365b57 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php @@ -97,7 +97,7 @@ public function onKernelResponse(ResponseEvent $event) return; } - $session = $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null; + $session = !$request->attributes->getBoolean('_stateless') && $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null; if ($session instanceof Session) { $usageIndexValue = $usageIndexReference = &$session->getUsageIndex(); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php index 57f8f53b1e9f7..fdf550d0ecd41 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ProfilerListenerTest.php @@ -40,8 +40,8 @@ public function testKernelTerminate() ->willReturn($profile); $kernel = $this->createMock(HttpKernelInterface::class); - $mainRequest = $this->createMock(Request::class); - $subRequest = $this->createMock(Request::class); + $mainRequest = new Request(); + $subRequest = new Request(); $response = $this->createMock(Response::class); $requestStack = new RequestStack(); diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 06f2c3907b2f6..a48ca7e38482e 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -95,7 +95,7 @@ public function authenticate(RequestEvent $event) } $request = $event->getRequest(); - $session = $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null; + $session = !$request->attributes->getBoolean('_stateless') && $request->hasPreviousSession() && $request->hasSession() ? $request->getSession() : null; $request->attributes->set('_security_firewall_run', $this->sessionKey); From e792b164202fd3167ffb98d74c583f9267dc28c2 Mon Sep 17 00:00:00 2001 From: Romain Jacquart Date: Tue, 18 Jun 2024 23:59:25 +0200 Subject: [PATCH 21/39] [Notifier] Fix thread key in GoogleChat bridge Google Chat API has deprecated the use of `threadKey` query parameter in favor of `thread.threadKey` in request's body. --- .../Bridge/GoogleChat/GoogleChatTransport.php | 12 +++++++++--- .../GoogleChat/Tests/GoogleChatTransportTest.php | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatTransport.php b/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatTransport.php index 41666a7cf182e..735744e5e6da4 100644 --- a/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatTransport.php +++ b/src/Symfony/Component/Notifier/Bridge/GoogleChat/GoogleChatTransport.php @@ -96,16 +96,22 @@ protected function doSend(MessageInterface $message): SentMessage $threadKey = $opts->getThreadKey() ?: $this->threadKey; - $options = $opts->toArray(); $url = sprintf('https://%s/v1/spaces/%s/messages?key=%s&token=%s%s', $this->getEndpoint(), $this->space, urlencode($this->accessKey), urlencode($this->accessToken), - $threadKey ? '&threadKey='.urlencode($threadKey) : '' + $threadKey ? '&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD' : '' ); + + $body = array_filter($opts->toArray()); + + if ($threadKey) { + $body['thread']['threadKey'] = $threadKey; + } + $response = $this->client->request('POST', $url, [ - 'json' => array_filter($options), + 'json' => $body, ]); try { diff --git a/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatTransportTest.php b/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatTransportTest.php index c8df301ca96c6..b6cbf8176d55c 100644 --- a/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatTransportTest.php +++ b/src/Symfony/Component/Notifier/Bridge/GoogleChat/Tests/GoogleChatTransportTest.php @@ -116,11 +116,11 @@ public function testSendWithOptions() ->method('getContent') ->willReturn('{"name":"spaces/My-Space/messages/abcdefg.hijklmno"}'); - $expectedBody = json_encode(['text' => $message]); + $expectedBody = json_encode(['text' => $message, 'thread' => ['threadKey' => 'My-Thread']]); $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { $this->assertSame('POST', $method); - $this->assertSame('https://chat.googleapis.com/v1/spaces/My-Space/messages?key=theAccessKey&token=theAccessToken%3D&threadKey=My-Thread', $url); + $this->assertSame('https://chat.googleapis.com/v1/spaces/My-Space/messages?key=theAccessKey&token=theAccessToken%3D&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD', $url); $this->assertSame($expectedBody, $options['body']); return $response; From add5d45fb0f07563f12a0c0b542372021d1cec73 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 19 Jun 2024 15:12:14 +0200 Subject: [PATCH 22/39] [HttpClient] Fix parsing SSE --- .../HttpClient/EventSourceHttpClient.php | 37 +++++---- .../Tests/EventSourceHttpClientTest.php | 78 +++++++++---------- 2 files changed, 55 insertions(+), 60 deletions(-) diff --git a/src/Symfony/Component/HttpClient/EventSourceHttpClient.php b/src/Symfony/Component/HttpClient/EventSourceHttpClient.php index 89d12e87764fa..6626cbeba6ba5 100644 --- a/src/Symfony/Component/HttpClient/EventSourceHttpClient.php +++ b/src/Symfony/Component/HttpClient/EventSourceHttpClient.php @@ -11,6 +11,7 @@ namespace Symfony\Component\HttpClient; +use Symfony\Component\HttpClient\Chunk\DataChunk; use Symfony\Component\HttpClient\Chunk\ServerSentEvent; use Symfony\Component\HttpClient\Exception\EventSourceException; use Symfony\Component\HttpClient\Response\AsyncContext; @@ -121,17 +122,30 @@ public function request(string $method, string $url, array $options = []): Respo return; } - $rx = '/((?:\r\n){2,}|\r{2,}|\n{2,})/'; - $content = $state->buffer.$chunk->getContent(); - if ($chunk->isLast()) { - $rx = substr_replace($rx, '|$', -2, 0); + if ('' !== $content = $state->buffer) { + $state->buffer = ''; + yield new DataChunk(-1, $content); + } + + yield $chunk; + + return; } - $events = preg_split($rx, $content, -1, \PREG_SPLIT_DELIM_CAPTURE); + + $content = $state->buffer.$chunk->getContent(); + $events = preg_split('/((?:\r\n){2,}|\r{2,}|\n{2,})/', $content, -1, \PREG_SPLIT_DELIM_CAPTURE); $state->buffer = array_pop($events); for ($i = 0; isset($events[$i]); $i += 2) { - $event = new ServerSentEvent($events[$i].$events[1 + $i]); + $content = $events[$i].$events[1 + $i]; + if (!preg_match('/(?:^|\r\n|[\r\n])[^:\r\n]/', $content)) { + yield new DataChunk(-1, $content); + + continue; + } + + $event = new ServerSentEvent($content); if ('' !== $event->getId()) { $context->setInfo('last_event_id', $state->lastEventId = $event->getId()); @@ -143,17 +157,6 @@ public function request(string $method, string $url, array $options = []): Respo yield $event; } - - if (preg_match('/^(?::[^\r\n]*+(?:\r\n|[\r\n]))+$/m', $state->buffer)) { - $content = $state->buffer; - $state->buffer = ''; - - yield $context->createChunk($content); - } - - if ($chunk->isLast()) { - yield $chunk; - } }); } } diff --git a/src/Symfony/Component/HttpClient/Tests/EventSourceHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/EventSourceHttpClientTest.php index fff3a0e7c18b7..536979e864672 100644 --- a/src/Symfony/Component/HttpClient/Tests/EventSourceHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/EventSourceHttpClientTest.php @@ -15,9 +15,11 @@ use Symfony\Component\HttpClient\Chunk\DataChunk; use Symfony\Component\HttpClient\Chunk\ErrorChunk; use Symfony\Component\HttpClient\Chunk\FirstChunk; +use Symfony\Component\HttpClient\Chunk\LastChunk; use Symfony\Component\HttpClient\Chunk\ServerSentEvent; use Symfony\Component\HttpClient\EventSourceHttpClient; use Symfony\Component\HttpClient\Exception\EventSourceException; +use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Component\HttpClient\Response\ResponseStream; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -34,7 +36,11 @@ class EventSourceHttpClientTest extends TestCase */ public function testGetServerSentEvents(string $sep) { - $rawData = <<assertSame(['Accept: text/event-stream', 'Cache-Control: no-cache'], $options['headers']); + + return new MockResponse([ + str_replace("\n", $sep, << false, 'http_method' => 'GET', 'url' => 'http://localhost:8080/events', 'response_headers' => ['content-type: text/event-stream']]); - $responseStream = new ResponseStream((function () use ($response, $chunk) { - yield $response => new FirstChunk(); - yield $response => $chunk; - yield $response => new ErrorChunk(0, 'timeout'); - })()); - - $hasCorrectHeaders = function ($options) { - $this->assertSame(['Accept: text/event-stream', 'Cache-Control: no-cache'], $options['headers']); - - return true; - }; - - $httpClient = $this->createMock(HttpClientInterface::class); - $httpClient->method('request')->with('GET', 'http://localhost:8080/events', $this->callback($hasCorrectHeaders))->willReturn($response); - - $httpClient->method('stream')->willReturn($responseStream); - - $es = new EventSourceHttpClient($httpClient); +TXT + ), + ], [ + 'canceled' => false, + 'http_method' => 'GET', + 'url' => 'http://localhost:8080/events', + 'response_headers' => ['content-type: text/event-stream'], + ]); + })); $res = $es->connect('http://localhost:8080/events'); $expected = [ new FirstChunk(), new ServerSentEvent(str_replace("\n", $sep, "event: builderror\nid: 46\ndata: {\"foo\": \"bar\"}\n\n")), new ServerSentEvent(str_replace("\n", $sep, "event: reload\nid: 47\ndata: {}\n\n")), - new ServerSentEvent(str_replace("\n", $sep, "event: reload\nid: 48\ndata: {}\n\n")), + new DataChunk(-1, str_replace("\n", $sep, ": this is a oneline comment\n\n")), + new DataChunk(-1, str_replace("\n", $sep, ": this is a\n: multiline comment\n\n")), + new ServerSentEvent(str_replace("\n", $sep, ": comments are ignored\nevent: reload\n: anywhere\nid: 48\ndata: {}\n\n")), new ServerSentEvent(str_replace("\n", $sep, "data: test\ndata:test\nid: 49\nevent: testEvent\n\n\n")), new ServerSentEvent(str_replace("\n", $sep, "id: 50\ndata: \ndata\ndata: \ndata\ndata: \n\n")), + new DataChunk(-1, str_replace("\n", $sep, "id: 60\ndata")), + new LastChunk("\r\n" === $sep ? 355 : 322), ]; - $i = 0; - - $this->expectExceptionMessage('Response has been canceled'); - while ($res) { - if ($i > 0) { - $res->cancel(); - } - foreach ($es->stream($res) as $chunk) { - if ($chunk->isTimeout()) { - continue; - } - - if ($chunk->isLast()) { - continue; - } - - $this->assertEquals($expected[$i++], $chunk); - } + foreach ($es->stream($res) as $chunk) { + $this->assertEquals(array_shift($expected), $chunk); } + $this->assertSame([], $expected); } /** From 69e8b2f9f0cb6669d13bc4420abf5eadcfec4fa7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 21 Jun 2024 11:18:42 +0200 Subject: [PATCH 23/39] Sync php-cs-fixer config file with 7.2 --- .php-cs-fixer.dist.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 853399385adc0..6d5d4c2dfa0a5 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -29,9 +29,11 @@ '@Symfony' => true, '@Symfony:risky' => true, 'protected_to_private' => false, - 'native_constant_invocation' => ['strict' => false], - 'nullable_type_declaration_for_default_null_value' => true, 'header_comment' => ['header' => $fileHeaderComment], + // TODO: Remove once the "compiler_optimized" set includes "sprintf" + 'native_function_invocation' => ['include' => ['@compiler_optimized', 'sprintf'], 'scope' => 'namespaced', 'strict' => true], + 'nullable_type_declaration' => true, + 'nullable_type_declaration_for_default_null_value' => true, ]) ->setRiskyAllowed(true) ->setFinder( @@ -40,29 +42,27 @@ ->append([__FILE__]) ->notPath('#/Fixtures/#') ->exclude([ - // directories containing files with content that is autogenerated by `var_export`, which breaks CS in output code - // fixture templates - 'Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Custom', - // resource templates - 'Symfony/Bundle/FrameworkBundle/Resources/views/Form', // explicit trigger_error tests 'Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/', 'Symfony/Component/Intl/Resources/data/', ]) + // explicit tests for ommited @param type, against `no_superfluous_phpdoc_tags` + ->notPath('Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php') + ->notPath('Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php') // Support for older PHPunit version ->notPath('Symfony/Bridge/PhpUnit/SymfonyTestsListener.php') ->notPath('#Symfony/Bridge/PhpUnit/.*Mock\.php#') ->notPath('#Symfony/Bridge/PhpUnit/.*Legacy#') // file content autogenerated by `var_export` ->notPath('Symfony/Component/Translation/Tests/fixtures/resources.php') - // file content autogenerated by `VarExporter::export` - ->notPath('Symfony/Component/Serializer/Tests/Fixtures/serializer.class.metadata.php') - // test template - ->notPath('Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Custom/_name_entry_label.html.php') // explicit trigger_error tests ->notPath('Symfony/Component/ErrorHandler/Tests/DebugClassLoaderTest.php') // stop removing spaces on the end of the line in strings ->notPath('Symfony/Component/Messenger/Tests/Command/FailedMessagesShowCommandTest.php') + // svg + ->notPath('Symfony/Component/ErrorHandler/Resources/assets/images/symfony-ghost.svg.php') + // HTML templates + ->notPath('#Symfony/.*\.html\.php#') ) ->setCacheFile('.php-cs-fixer.cache') ; From 79b03dbdc42892379bf3a1567b202e13219b3cab Mon Sep 17 00:00:00 2001 From: MatTheCat Date: Fri, 21 Jun 2024 15:04:29 +0200 Subject: [PATCH 24/39] [DoctrineBridge] Test reset with a true manager --- .../Doctrine/Tests/Fixtures/DummyManager.php | 69 +++++++++++++++++++ .../Doctrine/Tests/ManagerRegistryTest.php | 25 ++++--- 2 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php new file mode 100644 index 0000000000000..04e5a2acdd334 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php @@ -0,0 +1,69 @@ +testDumpContainerWithProxyServiceWillShareProxies(); + $container = new ContainerBuilder(); + + $container->register('foo', DummyManager::class)->setPublic(true); + $container->getDefinition('foo')->setLazy(true); + $container->compile(); + + $dumper = new PhpDumper($container); + $dumper->setProxyDumper(new ProxyDumper()); + eval('?>'.$dumper->dump(['class' => 'LazyServiceDoctrineBridgeContainer'])); } public function testResetService() { - $container = new \LazyServiceProjectServiceContainer(); + $container = new \LazyServiceDoctrineBridgeContainer(); $registry = new TestManagerRegistry('name', [], ['defaultManager' => 'foo'], 'defaultConnection', 'defaultManager', 'proxyInterfaceName'); $registry->setTestContainer($container); @@ -44,8 +51,8 @@ public function testResetService() $registry->resetManager(); $this->assertSame($foo, $container->get('foo')); - $this->assertInstanceOf(\stdClass::class, $foo); - $this->assertFalse(property_exists($foo, 'bar')); + $this->assertInstanceOf(DummyManager::class, $foo); + $this->assertFalse(isset($foo->bar)); } /** @@ -77,7 +84,7 @@ public function testResetServiceWillNotNestFurtherLazyServicesWithinEachOther() $service = $container->get('foo'); - self::assertInstanceOf(\stdClass::class, $service); + self::assertInstanceOf(DummyManager::class, $service); self::assertInstanceOf(LazyLoadingInterface::class, $service); self::assertInstanceOf(ValueHolderInterface::class, $service); self::assertFalse($service->isProxyInitialized()); @@ -91,7 +98,7 @@ public function testResetServiceWillNotNestFurtherLazyServicesWithinEachOther() $service->initializeProxy(); $wrappedValue = $service->getWrappedValueHolderValue(); - self::assertInstanceOf(\stdClass::class, $wrappedValue); + self::assertInstanceOf(DummyManager::class, $wrappedValue); self::assertNotInstanceOf(LazyLoadingInterface::class, $wrappedValue); self::assertNotInstanceOf(ValueHolderInterface::class, $wrappedValue); } @@ -104,7 +111,7 @@ private function dumpLazyServiceProjectAsFilesServiceContainer() $container = new ContainerBuilder(); - $container->register('foo', \stdClass::class) + $container->register('foo', DummyManager::class) ->setPublic(true) ->setLazy(true); $container->compile(); From 5f16bbdce11dc2b6b28f6e41046cd2c1b85d1c90 Mon Sep 17 00:00:00 2001 From: MatTheCat Date: Thu, 20 Jun 2024 16:39:18 +0200 Subject: [PATCH 25/39] =?UTF-8?q?[SecurityBundle]=20Add=20`provider`=20XML?= =?UTF-8?q?=20attribute=20to=20the=20authenticators=20it=E2=80=99s=20missi?= =?UTF-8?q?ng=20from?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SecurityBundle/Resources/config/schema/security-1.0.xsd | 1 + .../Tests/DependencyInjection/Fixtures/xml/container1.xml | 3 +-- .../DependencyInjection/Fixtures/xml/firewall_provider.xml | 2 +- .../Fixtures/xml/firewall_undefined_provider.xml | 2 +- .../DependencyInjection/Fixtures/xml/legacy_container1.xml | 3 +-- .../Tests/DependencyInjection/Fixtures/xml/legacy_encoders.xml | 3 +-- .../DependencyInjection/Fixtures/xml/listener_provider.xml | 2 +- .../Fixtures/xml/listener_undefined_provider.xml | 2 +- .../Fixtures/xml/no_custom_user_checker.xml | 1 - 9 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/schema/security-1.0.xsd b/src/Symfony/Bundle/SecurityBundle/Resources/config/schema/security-1.0.xsd index 70b682e4065ca..1a367b8397213 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/schema/security-1.0.xsd +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/schema/security-1.0.xsd @@ -230,6 +230,7 @@ + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index c97dd5bf7ebf0..01ecdbaecc5c4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -64,9 +64,8 @@ - + - app.user_checker ROLE_USER diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml index 6f74984045970..66da3c4a28307 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml @@ -15,7 +15,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml index a80f613e00331..a55ffdacc2fc3 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml @@ -15,7 +15,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_container1.xml index ed7afe5e833ee..15f27b4ff1351 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_container1.xml @@ -66,10 +66,9 @@ - + - app.user_checker ROLE_USER diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_encoders.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_encoders.xml index a362a59a15b80..cb5c04b7f82aa 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_encoders.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/legacy_encoders.xml @@ -66,10 +66,9 @@ - + - app.user_checker ROLE_USER diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml index b45f378a5ba68..d4a6a1d41aa47 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml @@ -15,7 +15,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml index bdf9d5ec837f0..312cb803960d2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml @@ -15,7 +15,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml index c4dea529ba452..fe81171b56977 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml @@ -22,7 +22,6 @@ - From 5468d3848ce90ea63a28a29771da6dd83f04638e Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Wed, 26 Jun 2024 13:42:50 +0200 Subject: [PATCH 26/39] [String] Add `alias` case to `EnglishInflector` --- src/Symfony/Component/String/Inflector/EnglishInflector.php | 3 +++ .../Component/String/Tests/Inflector/EnglishInflectorTest.php | 1 + 2 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/String/Inflector/EnglishInflector.php b/src/Symfony/Component/String/Inflector/EnglishInflector.php index e068fcbcd6d98..77ebc134a436f 100644 --- a/src/Symfony/Component/String/Inflector/EnglishInflector.php +++ b/src/Symfony/Component/String/Inflector/EnglishInflector.php @@ -289,6 +289,9 @@ final class EnglishInflector implements InflectorInterface // atlases (atlas) ['salta', 5, true, true, 'atlases'], + // aliases (alias) + ['saila', 5, true, true, 'aliases'], + // irises (iris) ['siri', 4, true, true, 'irises'], diff --git a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php index 6744814b66603..fb5d04300305a 100644 --- a/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php +++ b/src/Symfony/Component/String/Tests/Inflector/EnglishInflectorTest.php @@ -317,6 +317,7 @@ public static function pluralizeProvider() ['hippocampus', 'hippocampi'], ['campus', 'campuses'], ['hardware', 'hardware'], + ['alias', 'aliases'], // test casing: if the first letter was uppercase, it should remain so ['Man', 'Men'], From f93113e80ef4799793db5cf4140ac4bdbf2a8c17 Mon Sep 17 00:00:00 2001 From: Boris Grishenko Date: Sat, 22 Jun 2024 21:53:47 +0200 Subject: [PATCH 27/39] [String] Fix *String::snake methods The ByteString::snake and AbstractUnitcodeString::snake methods had a bug that caused incorrect string conversion results for all uppercase words separated by space or "_" character. Ex. "GREAT SYMFONY" was converted to "greatsymfony" instead of "great_symfony" --- src/Symfony/Component/String/AbstractUnicodeString.php | 4 ++-- src/Symfony/Component/String/ByteString.php | 4 ++-- src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/String/AbstractUnicodeString.php b/src/Symfony/Component/String/AbstractUnicodeString.php index 239f234239fb8..0f840f19d717d 100644 --- a/src/Symfony/Component/String/AbstractUnicodeString.php +++ b/src/Symfony/Component/String/AbstractUnicodeString.php @@ -366,8 +366,8 @@ public function reverse(): parent public function snake(): parent { - $str = $this->camel(); - $str->string = mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1_\2', $str->string), 'UTF-8'); + $str = clone $this; + $str->string = str_replace(' ', '_', mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1 \2', $str->string), 'UTF-8')); return $str; } diff --git a/src/Symfony/Component/String/ByteString.php b/src/Symfony/Component/String/ByteString.php index 05170da801c0e..86887d7901a74 100644 --- a/src/Symfony/Component/String/ByteString.php +++ b/src/Symfony/Component/String/ByteString.php @@ -366,8 +366,8 @@ public function slice(int $start = 0, ?int $length = null): parent public function snake(): parent { - $str = $this->camel(); - $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string)); + $str = clone $this; + $str->string = str_replace(' ', '_', strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1 \2', $str->string))); return $str; } diff --git a/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php b/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php index 8bde9bc8b3df3..132d558dbade4 100644 --- a/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php +++ b/src/Symfony/Component/String/Tests/AbstractAsciiTestCase.php @@ -1077,6 +1077,8 @@ public static function provideSnake() ['symfony_is_great', 'symfonyIsGREAT'], ['symfony_is_really_great', 'symfonyIsREALLYGreat'], ['symfony', 'SYMFONY'], + ['symfony_is_great', 'SYMFONY IS GREAT'], + ['symfony_is_great', 'SYMFONY_IS_GREAT'], ]; } From d23ea3335d7ed8bd2e384f2c00430f04c16580e0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 27 Jun 2024 09:48:26 +0200 Subject: [PATCH 28/39] Ibexa is sponsoring Symfony 5.4, thanks to them! \o/ --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7c4f1a85899bb..8ef86422a84ae 100644 --- a/README.md +++ b/README.md @@ -17,13 +17,17 @@ Installation Sponsor ------- -Symfony 5.4 is [backed][27] by [Private Packagist][28]. +Symfony 5.4 is [backed][27] by [Private Packagist][28] and [Ibexa][29]. Private Packagist is a fast, reliable, and secure Composer repository for your private packages. It mirrors all your open-source dependencies for better availability and monitors them for security vulnerabilities. -Help Symfony by [sponsoring][29] its development! +Ibexa is the leading DXP for Symfony developers. Ibexa DXP is used across the +world by thousands of websites/shops/portals and supported by a fantastic, +passionate community of developers, agencies, and users. They love Symfony! + +Help Symfony by [sponsoring][30] its development! Documentation ------------- @@ -87,4 +91,5 @@ and supported by [Symfony contributors][19]. [26]: https://symfony.com/book [27]: https://symfony.com/backers [28]: https://packagist.com/ -[29]: https://symfony.com/sponsor +[29]: https://ibexa.co/ +[30]: https://symfony.com/sponsor From 2fc878977aac0a41e956721ea6e59006d134b636 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Thu, 27 Jun 2024 18:09:31 +0200 Subject: [PATCH 29/39] [Serializer] Check if exception message in test is correct --- .../Serializer/Tests/Fixtures/NotNormalizableDummy.php | 2 +- .../Tests/Normalizer/AbstractObjectNormalizerTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/NotNormalizableDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/NotNormalizableDummy.php index 86ee6dbe5da91..d146c1a8b1aa8 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/NotNormalizableDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/NotNormalizableDummy.php @@ -26,6 +26,6 @@ public function __construct() public function denormalize(DenormalizerInterface $denormalizer, $data, ?string $format = null, array $context = []) { - throw new NotNormalizableValueException(); + throw new NotNormalizableValueException('Custom exception message'); } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index afaf57ea06b52..b700f6ee713f6 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -514,6 +514,7 @@ public function testDenormalizeUntypedFormat() public function testDenormalizeUntypedFormatNotNormalizable() { $this->expectException(NotNormalizableValueException::class); + $this->expectExceptionMessage('Custom exception message'); $serializer = new Serializer([new CustomNormalizer(), new ObjectNormalizer(null, null, null, new PropertyInfoExtractor([], [new PhpDocExtractor(), new ReflectionExtractor()]))]); $serializer->denormalize(['value' => 'test'], DummyWithNotNormalizable::class, 'xml'); } From 786abd125e13131ea5b982ae692373f0f8b677ba Mon Sep 17 00:00:00 2001 From: bocharsky-bw Date: Thu, 27 Jun 2024 22:38:52 +0200 Subject: [PATCH 30/39] Fix typo: synchronous -> synchronously --- src/Symfony/Component/Mailer/MailerInterface.php | 2 +- src/Symfony/Component/Notifier/ChatterInterface.php | 2 +- src/Symfony/Component/Notifier/TexterInterface.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Mailer/MailerInterface.php b/src/Symfony/Component/Mailer/MailerInterface.php index 8d9540a3e5e3f..ebac4b53efa4e 100644 --- a/src/Symfony/Component/Mailer/MailerInterface.php +++ b/src/Symfony/Component/Mailer/MailerInterface.php @@ -15,7 +15,7 @@ use Symfony\Component\Mime\RawMessage; /** - * Interface for mailers able to send emails synchronous and/or asynchronous. + * Interface for mailers able to send emails synchronously and/or asynchronously. * * Implementations must support synchronous and asynchronous sending. * diff --git a/src/Symfony/Component/Notifier/ChatterInterface.php b/src/Symfony/Component/Notifier/ChatterInterface.php index 915190e623aaa..6d89ca921e970 100644 --- a/src/Symfony/Component/Notifier/ChatterInterface.php +++ b/src/Symfony/Component/Notifier/ChatterInterface.php @@ -14,7 +14,7 @@ use Symfony\Component\Notifier\Transport\TransportInterface; /** - * Interface for classes able to send chat messages synchronous and/or asynchronous. + * Interface for classes able to send chat messages synchronously and/or asynchronously. * * @author Fabien Potencier */ diff --git a/src/Symfony/Component/Notifier/TexterInterface.php b/src/Symfony/Component/Notifier/TexterInterface.php index e65547755cd70..a044bb6d5d835 100644 --- a/src/Symfony/Component/Notifier/TexterInterface.php +++ b/src/Symfony/Component/Notifier/TexterInterface.php @@ -14,7 +14,7 @@ use Symfony\Component\Notifier\Transport\TransportInterface; /** - * Interface for classes able to send SMS messages synchronous and/or asynchronous. + * Interface for classes able to send SMS messages synchronously and/or asynchronously. * * @author Fabien Potencier */ From de0cd23dc30cf0dfcf2ed930238409e660f099d0 Mon Sep 17 00:00:00 2001 From: Gerard Date: Fri, 28 Jun 2024 00:48:14 +0200 Subject: [PATCH 31/39] Reviewed Catalan missing translations --- .../Security/Core/Resources/translations/security.ca.xlf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf index 6d7dc7fc23e33..93ff24f330735 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf @@ -64,7 +64,7 @@ Too many failed login attempts, please try again later. - Massa intents d'inici de sessió fallits, torneu-ho a provar més tard. + Massa intents d'inici de sessió fallits, si us plau torneu-ho a provar més tard. Invalid or expired login link. @@ -72,11 +72,11 @@ Too many failed login attempts, please try again in %minutes% minute. - Massa intents d'inici de sessió fallits, torneu-ho a provar en %minutes% minut. + Massa intents d'inici de sessió fallits, si us plau torneu-ho a provar en %minutes% minut. Too many failed login attempts, please try again in %minutes% minutes. - Massa intents fallits d'inici de sessió, torneu-ho a provar d'aquí a %minutes% minuts. + Massa intents d'inici de sessió fallits, si us plau torneu-ho a provar en %minutes% minuts. From efc93cdfe6b3907220f59f435886338773a0b034 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 27 Jun 2024 17:05:20 +0200 Subject: [PATCH 32/39] [HttpClient][Mailer] Revert "Let curl handle transfer encoding", use HTTP/1.1 for Mailgun --- src/Symfony/Component/HttpClient/CurlHttpClient.php | 5 +++-- .../Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index 4c5ced322d5de..3a2fba025aeff 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -246,8 +246,9 @@ public function request(string $method, string $url, array $options = []): Respo if (isset($options['normalized_headers']['content-length'][0])) { $curlopts[\CURLOPT_INFILESIZE] = (int) substr($options['normalized_headers']['content-length'][0], \strlen('Content-Length: ')); - } elseif (!isset($options['normalized_headers']['transfer-encoding'])) { - $curlopts[\CURLOPT_INFILESIZE] = -1; + } + if (!isset($options['normalized_headers']['transfer-encoding'])) { + $curlopts[\CURLOPT_HTTPHEADER][] = 'Transfer-Encoding:'.(isset($curlopts[\CURLOPT_INFILESIZE]) ? '' : ' chunked'); } if ('POST' !== $method) { diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php index c621ae5b16a77..5fa28ef0e494b 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php @@ -63,6 +63,7 @@ protected function doSendHttp(SentMessage $message): ResponseInterface $endpoint = sprintf('%s/v3/%s/messages.mime', $this->getEndpoint(), urlencode($this->domain)); $response = $this->client->request('POST', 'https://'.$endpoint, [ + 'http_version' => '1.1', 'auth_basic' => 'api:'.$this->key, 'headers' => $headers, 'body' => $body->bodyToIterable(), From 0a7477d7540c7d1f954b36d65d8a9c85eee30df6 Mon Sep 17 00:00:00 2001 From: Quynh Nguyen Date: Fri, 28 Jun 2024 14:45:31 +0700 Subject: [PATCH 33/39] Test convert CompletionInput into string --- .../Console/Completion/CompletionInput.php | 2 +- .../Tests/Completion/CompletionInputTest.php | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Completion/CompletionInput.php b/src/Symfony/Component/Console/Completion/CompletionInput.php index 368b945079484..2f631bcd8484f 100644 --- a/src/Symfony/Component/Console/Completion/CompletionInput.php +++ b/src/Symfony/Component/Console/Completion/CompletionInput.php @@ -53,7 +53,7 @@ public static function fromString(string $inputStr, int $currentIndex): self * Create an input based on an COMP_WORDS token list. * * @param string[] $tokens the set of split tokens (e.g. COMP_WORDS or argv) - * @param $currentIndex the index of the cursor (e.g. COMP_CWORD) + * @param int $currentIndex the index of the cursor (e.g. COMP_CWORD) */ public static function fromTokens(array $tokens, int $currentIndex): self { diff --git a/src/Symfony/Component/Console/Tests/Completion/CompletionInputTest.php b/src/Symfony/Component/Console/Tests/Completion/CompletionInputTest.php index d98da682cd90d..65708d3ec8659 100644 --- a/src/Symfony/Component/Console/Tests/Completion/CompletionInputTest.php +++ b/src/Symfony/Component/Console/Tests/Completion/CompletionInputTest.php @@ -133,4 +133,19 @@ public static function provideFromStringData() yield ['bin/console cache:clear "multi word string"', ['bin/console', 'cache:clear', '"multi word string"']]; yield ['bin/console cache:clear \'multi word string\'', ['bin/console', 'cache:clear', '\'multi word string\'']]; } + + public function testToString() + { + $input = CompletionInput::fromTokens(['foo', 'bar', 'baz'], 0); + $this->assertSame('foo| bar baz', (string) $input); + + $input = CompletionInput::fromTokens(['foo', 'bar', 'baz'], 1); + $this->assertSame('foo bar| baz', (string) $input); + + $input = CompletionInput::fromTokens(['foo', 'bar', 'baz'], 2); + $this->assertSame('foo bar baz|', (string) $input); + + $input = CompletionInput::fromTokens(['foo', 'bar', 'baz'], 11); + $this->assertSame('foo bar baz |', (string) $input); + } } From a319e94d0b2ea350e40a112c3cb9ddb8631bdc1b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Jun 2024 10:53:38 +0200 Subject: [PATCH 34/39] [DoctrineBridge] Fix compat with DI >= 6.4 --- src/Symfony/Bridge/Doctrine/ManagerRegistry.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index c3d48fc558518..b290ae5d9b039 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -72,6 +72,8 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { } if (isset($this->fileMap[$name])) { $wrappedInstance = $this->load($this->fileMap[$name], false); + } elseif ((new \ReflectionMethod($this, $this->methodMap[$name]))->isStatic()) { + $wrappedInstance = $this->{$this->methodMap[$name]}($this, false); } else { $wrappedInstance = $this->{$this->methodMap[$name]}(false); } From 2b50dea4f6164db0dd84bee3f8566a19c23a4f59 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Jun 2024 11:10:31 +0200 Subject: [PATCH 35/39] [Filesystem] Fix Filesystem::remove() on Windows --- src/Symfony/Component/Filesystem/Filesystem.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 700311d5843fc..958ef178db2fb 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -173,7 +173,7 @@ private static function doRemove(array $files, bool $isRecursive): void } } elseif (is_dir($file)) { if (!$isRecursive) { - $tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-_')); + $tmpName = \dirname(realpath($file)).'/.!'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-!')); if (file_exists($tmpName)) { try { From c3bf9a60746cd04cf8f98f817e38d1617b02959e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Jun 2024 11:36:24 +0200 Subject: [PATCH 36/39] [Filesystem][Mime] Fix transient tests --- src/Symfony/Component/Filesystem/Tests/FilesystemTest.php | 6 +++--- src/Symfony/Component/Mime/Tests/Part/DataPartTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 101f30f898714..eea5fe1a68952 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -171,17 +171,17 @@ public function testCopyForOriginUrlsAndExistingLocalFileDefaultsToCopy() } $finder = new PhpExecutableFinder(); - $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', 'localhost:8057'])); + $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', 'localhost:8857'])); $process->setWorkingDirectory(__DIR__.'/Fixtures/web'); $process->start(); do { usleep(50000); - } while (!@fopen('http://localhost:8057', 'r')); + } while (!@fopen('http://localhost:8857', 'r')); try { - $sourceFilePath = 'http://localhost:8057/logo_symfony_header.png'; + $sourceFilePath = 'http://localhost:8857/logo_symfony_header.png'; $targetFilePath = $this->workspace.\DIRECTORY_SEPARATOR.'copy_target_file'; file_put_contents($targetFilePath, 'TARGET FILE'); $this->filesystem->copy($sourceFilePath, $targetFilePath, false); diff --git a/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php b/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php index 3d306f2e8ff86..7a9913b969a64 100644 --- a/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php +++ b/src/Symfony/Component/Mime/Tests/Part/DataPartTest.php @@ -143,15 +143,15 @@ public function testFromPathWithUrl() } $finder = new PhpExecutableFinder(); - $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', 'localhost:8057'])); + $process = new Process(array_merge([$finder->find(false)], $finder->findArguments(), ['-dopcache.enable=0', '-dvariables_order=EGPCS', '-S', 'localhost:8856'])); $process->setWorkingDirectory(__DIR__.'/../Fixtures/web'); $process->start(); try { do { usleep(50000); - } while (!@fopen('http://localhost:8057', 'r')); - $p = DataPart::fromPath($file = 'http://localhost:8057/logo_symfony_header.png'); + } while (!@fopen('http://localhost:8856', 'r')); + $p = DataPart::fromPath($file = 'http://localhost:8856/logo_symfony_header.png'); $content = file_get_contents($file); $this->assertEquals($content, $p->getBody()); $maxLineLength = 76; From ad6d2fc33629eba1dcd24d5ac90c91a7b2879667 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 28 Jun 2024 13:42:34 +0200 Subject: [PATCH 37/39] Update CHANGELOG for 5.4.41 --- CHANGELOG-5.4.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG-5.4.md b/CHANGELOG-5.4.md index 3e2bcd6d8360d..c160dd4fef756 100644 --- a/CHANGELOG-5.4.md +++ b/CHANGELOG-5.4.md @@ -7,6 +7,31 @@ in 5.4 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.4.0...v5.4.1 +* 5.4.41 (2024-06-28) + + * bug #57497 [String] Fixed u()->snake(), b()->snake() and s()->snake() methods (arczinosek) + * bug #57574 [Filesystem] Fix Filesystem::remove() on Windows (nicolas-grekas) + * bug #57572 [DoctrineBridge] Fix compat with DI >= 6.4 (nicolas-grekas) + * bug #57538 [String] Add `alias` case to `EnglishInflector` (alexandre-daubois) + * feature #57557 Ibexa is sponsoring Symfony 5.4, thanks to them! \o/ (nicolas-grekas) + * bug #57569 [HttpClient][Mailer] Revert "Let curl handle transfer encoding", use HTTP/1.1 for Mailgun (nicolas-grekas) + * bug #57453 [HttpClient] Fix parsing SSE (fancyweb) + * bug #57467 [SecurityBundle] Add `provider` XML attribute to the authenticators it’s missing from (MatTheCat) + * bug #57384 [Notifier] Fix thread key in GoogleChat bridge (romain-jacquart) + * bug #57372 [HttpKernel][Security] Fix accessing session for stateless request (VincentLanglet) + * bug #57112 [Messenger] Handle `AMQPConnectionException` when publishing a message (jwage) + * bug #57341 [Serializer] properly handle invalid data for false/true types (xabbuh) + * bug #57187 [Serializer] Fix `ObjectNormalizer` with property path (HypeMC) + * bug #57355 [ErrorHandler] Fix rendered exception code highlighting on PHP 8.3 (tscni) + * bug #57273 [FrameworkBundle] Fix setting default context for certain normalizers (HypeMC) + * bug #52699 [Serializer] [PropertyAccessor] Ignore non-collection interface generics (mtarld) + * bug #54634 [String] Fix #54611 pluralization of -on ending words + singularization of -a ending foreign words (Geordie, DesLynx) + * bug #57213 [Validator] [UniqueValidator] Use correct variable as parameter in (custom) error message (seho-nl, Sebastien Hoek) + * bug #54920 [Messenger] Comply with Amazon SQS requirements for message body (VincentLanglet) + * bug #57110 [PhpUnitBridge] Fix error handler triggered outside of tests (HypeMC) + * bug #57297 [FrameworkBundle] not registered definitions must not be modified (xabbuh) + * bug #57234 [String] Fix Inflector for 'hardware' (podhy) + * 5.4.40 (2024-06-02) * bug #57275 Fix autoload configs to avoid warnings when building optimized autoloaders (Seldaek) From 023a565bdfbc586753c724813425868316eed593 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 28 Jun 2024 13:42:39 +0200 Subject: [PATCH 38/39] Update CONTRIBUTORS for 5.4.41 --- CONTRIBUTORS.md | 60 ++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 92dac23ccbd1c..8542f255df6a1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -33,9 +33,9 @@ The Symfony Connect username in parenthesis allows to get more information - Hugo Hamon (hhamon) - Tobias Nyholm (tobias) - Jérôme Tamarelle (gromnan) + - HypeMC (hypemc) - Samuel ROZE (sroze) - Antoine Lamirault (alamirault) - - HypeMC (hypemc) - Pascal Borreli (pborreli) - Romain Neutron - Joseph Bielawski (stloyd) @@ -54,8 +54,8 @@ The Symfony Connect username in parenthesis allows to get more information - Gabriel Ostrolucký (gadelat) - Matthias Pigulla (mpdude) - Jonathan Wage (jwage) - - Valentin Udaltsov (vudaltsov) - Vincent Langlet (deviling) + - Valentin Udaltsov (vudaltsov) - Alexandre Salomé (alexandresalome) - Grégoire Paris (greg0ire) - William DURAND @@ -72,11 +72,11 @@ The Symfony Connect username in parenthesis allows to get more information - Pierre du Plessis (pierredup) - David Maicher (dmaicher) - Bulat Shakirzyanov (avalanche123) + - Mathias Arlaud (mtarld) - Iltar van der Berg - Miha Vrhovnik (mvrhov) - Tomasz Kowalczyk (thunderer) - Gary PEGEOT (gary-p) - - Mathias Arlaud (mtarld) - Saša Stamenković (umpirsky) - Allison Guilhem (a_guilhem) - Mathieu Piot (mpiot) @@ -90,9 +90,9 @@ The Symfony Connect username in parenthesis allows to get more information - Bilal Amarni (bamarni) - Eriksen Costa - Florin Patan (florinpatan) + - Dariusz Ruminski - Vladimir Reznichenko (kalessil) - Peter Rehm (rpet) - - Dariusz Ruminski - Henrik Bjørnskov (henrikbjorn) - David Buchmann (dbu) - Ruud Kamphuis (ruudk) @@ -107,16 +107,16 @@ The Symfony Connect username in parenthesis allows to get more information - Douglas Greenshields (shieldo) - Frank A. Fiebig (fafiebig) - Baldini + - Tomas Norkūnas (norkunas) - Alex Pott - Fran Moreno (franmomu) - Charles Sarrazin (csarrazi) - - Tomas Norkūnas (norkunas) - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Ener-Getick - Hubert Lenoir (hubert_lenoir) - - Graham Campbell (graham) + - Ener-Getick - Antoine Makdessi (amakdessi) + - Graham Campbell (graham) - Tugdual Saunier (tucksaun) - Lee McDermott - Brandon Turner @@ -171,17 +171,17 @@ The Symfony Connect username in parenthesis allows to get more information - Gordon Franke (gimler) - Malte Schlüter (maltemaltesich) - jeremyFreeAgent (jeremyfreeagent) + - Michael Babker (mbabker) + - Maximilian Beckers (maxbeckers) + - Valtteri R (valtzu) - Joshua Thijssen - Vasilij Dusko - Daniel Wehner (dawehner) - Maxime Helias (maxhelias) - Robert Schönthal (digitalkaoz) - Smaine Milianni (ismail1432) - - Michael Babker (mbabker) - François-Xavier de Guillebon (de-gui_f) - - Maximilian Beckers (maxbeckers) - noniagriconomie - - Valtteri R (valtzu) - Eric GELOEN (gelo) - Gabriel Caruso - Stefano Sala (stefano.sala) @@ -405,6 +405,7 @@ The Symfony Connect username in parenthesis allows to get more information - Danny Berger (dpb587) - Alif Rachmawadi - Anton Chernikov (anton_ch1989) + - Stiven Llupa (sllupa) - Pierre-Yves Lebecq (pylebecq) - Benjamin Leveque (benji07) - Jordan Samouh (jordansamouh) @@ -438,6 +439,7 @@ The Symfony Connect username in parenthesis allows to get more information - Dane Powell - Sebastien Morel (plopix) - Christopher Davis (chrisguitarguy) + - Jonathan H. Wage - Loïc Frémont (loic425) - Matthieu Auger (matthieuauger) - Sergey Belyshkin (sbelyshkin) @@ -468,11 +470,11 @@ The Symfony Connect username in parenthesis allows to get more information - Wouter Van Hecke - Baptiste Lafontaine (magnetik) - Iker Ibarguren (ikerib) + - Michael Hirschler (mvhirsch) - Michael Holm (hollo) - Blanchon Vincent (blanchonvincent) - Christian Schmidt - Ben Hakim - - Stiven Llupa (sllupa) - Marco Petersen (ocrampete16) - Bohan Yang (brentybh) - Vilius Grigaliūnas @@ -520,7 +522,6 @@ The Symfony Connect username in parenthesis allows to get more information - Thierry T (lepiaf) - Lorenz Schori - Lukáš Holeczy (holicz) - - Jonathan H. Wage - Jeremy Livingston (jeremylivingston) - ivan - SUMIDA, Ippei (ippey_s) @@ -541,7 +542,6 @@ The Symfony Connect username in parenthesis allows to get more information - Francesco Levorato - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) - - Michael Hirschler (mvhirsch) - Gyula Sallai (salla) - Hendrik Luup (hluup) - Inal DJAFAR (inalgnu) @@ -582,6 +582,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sanpi (sanpi) - Eduardo Gulias (egulias) - giulio de donato (liuggio) + - Ivan Mezinov - ShinDarth - Stéphane PY (steph_py) - Cătălin Dan (dancatalin) @@ -649,6 +650,7 @@ The Symfony Connect username in parenthesis allows to get more information - quentin neyrat (qneyrat) - Chris Tanaskoski (devristo) - Steffen Roßkamp + - Andrey Lebedev (alebedev) - Alexandru Furculita (afurculita) - Michel Salib (michelsalib) - Ben Roberts (benr77) @@ -750,7 +752,6 @@ The Symfony Connect username in parenthesis allows to get more information - Roberto Espinoza (respinoza) - Pierre Rineau - Soufian EZ ZANTAR (soezz) - - Ivan Mezinov - Marek Zajac - Adam Harvey - ilyes kooli (skafandri) @@ -764,6 +765,7 @@ The Symfony Connect username in parenthesis allows to get more information - Patrick Reimers (preimers) - Brayden Williams (redstar504) - insekticid + - Kieran Brahney - Jérémy M (th3mouk) - Trent Steel (trsteel88) - boombatower @@ -785,6 +787,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matthew Grasmick - Miroslav Šustek (sustmi) - Pablo Díez (pablodip) + - Kev - Kevin McBride - Sergio Santoro - Philipp Rieber (bicpi) @@ -909,7 +912,6 @@ The Symfony Connect username in parenthesis allows to get more information - Ramunas Pabreza (doobas) - Yuriy Vilks (igrizzli) - Terje Bråten - - Andrey Lebedev (alebedev) - Sebastian Krebs - Piotr Stankowski - Pierre-Emmanuel Tanguy (petanguy) @@ -1011,6 +1013,7 @@ The Symfony Connect username in parenthesis allows to get more information - Aurimas Niekis (gcds) - Vincent Chalamon - Matthieu Calie (matth--) + - Sem Schidler (xvilo) - Benjamin Schoch (bschoch) - Martins Sipenko - Guilherme Augusto Henschel @@ -1057,6 +1060,7 @@ The Symfony Connect username in parenthesis allows to get more information - Ivan Grigoriev (greedyivan) - Johann Saunier (prophet777) - Kevin SCHNEKENBURGER + - Geordie - Fabien Salles (blacked) - Andreas Erhard (andaris) - alexpozzi @@ -1135,11 +1139,11 @@ The Symfony Connect username in parenthesis allows to get more information - Aleksandr Volochnev (exelenz) - Robin van der Vleuten (robinvdvleuten) - Grinbergs Reinis (shima5) - - Kieran Brahney - Klaus Silveira (klaussilveira) - Michael Piecko (michael.piecko) - Toni Peric (tperic) - yclian + - Nicolas DOUSSON - radar3301 - Aleksey Prilipko - Jelle Raaijmakers (gmta) @@ -1148,7 +1152,6 @@ The Symfony Connect username in parenthesis allows to get more information - Wybren Koelmans (wybren_koelmans) - Roberto Nygaard - victor-prdh - - Kev - Davide Borsatto (davide.borsatto) - Florian Hermann (fhermann) - zenas1210 @@ -1182,6 +1185,7 @@ The Symfony Connect username in parenthesis allows to get more information - Mathias Brodala (mbrodala) - Robert Fischer (sandoba) - Tarjei Huse (tarjei) + - Travis Carden (traviscarden) - mfettig - Besnik Br - Issam Raouf (iraouf) @@ -1243,6 +1247,7 @@ The Symfony Connect username in parenthesis allows to get more information - Volodymyr Panivko - kick-the-bucket - fedor.f + - roman joly (eltharin) - Yosmany Garcia (yosmanyga) - Jeremiasz Major - Jibé Barth (jibbarth) @@ -1262,6 +1267,7 @@ The Symfony Connect username in parenthesis allows to get more information - possum - Denis Zunke (donalberto) - Adrien Roches (neirda24) + - Thomas Trautner (thomastr) - _sir_kane (waly) - Olivier Maisonneuve - Gálik Pál @@ -1292,6 +1298,7 @@ The Symfony Connect username in parenthesis allows to get more information - Zhuravlev Alexander (scif) - Stefano Degenkamp (steef) - James Michael DuPont + - Tinjo Schöni - Carlos Buenosvinos (carlosbuenosvinos) - Christian Gripp (core23) - Jake (jakesoft) @@ -1350,6 +1357,7 @@ The Symfony Connect username in parenthesis allows to get more information - Ana Raro - Ana Raro - Tony Malzhacker + - Cosmin Sandu - Andreas Lutro (anlutro) - DUPUCH (bdupuch) - Cyril Quintin (cyqui) @@ -1399,6 +1407,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matthieu Mota (matthieumota) - Maxime Pinot (maximepinot) - Jean-Baptiste GOMOND (mjbgo) + - Jakub Podhorsky (podhy) - abdul malik ikhsan (samsonasik) - Henry Snoek (snoek09) - Morgan Auchede @@ -1430,6 +1439,7 @@ The Symfony Connect username in parenthesis allows to get more information - Johnson Page (jwpage) - Kuba Werłos (kuba) - Ruben Gonzalez (rubenruateltek) + - Mokhtar Tlili (sf-djuba) - Michael Roterman (wtfzdotnet) - Philipp Keck - Pavol Tuka @@ -1470,6 +1480,7 @@ The Symfony Connect username in parenthesis allows to get more information - Nicolas de Marqué (nicola) - Thiago Cordeiro (thiagocordeiro) - Matthieu Bontemps + - Ian Irlen - Rootie - Sébastien Santoro (dereckson) - Daniel Alejandro Castro Arellano (lexcast) @@ -1671,6 +1682,7 @@ The Symfony Connect username in parenthesis allows to get more information - Bruno Rodrigues de Araujo (brunosinister) - Máximo Cuadros (mcuadros) - Jacek Wilczyński (jacekwilczynski) + - Christoph Kappestein - Camille Baronnet - EXT - THERAGE Kevin - tamirvs @@ -1832,11 +1844,11 @@ The Symfony Connect username in parenthesis allows to get more information - Peter Smeets (darkspartan) - Julien Bianchi (jubianchi) - Michael Dawart (mdawart) - - Sem Schidler (xvilo) - Robert Meijers - Tijs Verkoyen - James Sansbury - Marcin Chwedziak + - Dan Kadera - hjkl - Dan Wilga - Thijs Reijgersberg @@ -2271,7 +2283,6 @@ The Symfony Connect username in parenthesis allows to get more information - DidierLmn - Pedro Silva - Chihiro Adachi (chihiro-adachi) - - Thomas Trautner (thomastr) - Jeroen de Graaf - Ulrik McArdle - BiaDd @@ -2292,6 +2303,7 @@ The Symfony Connect username in parenthesis allows to get more information - Fabian Haase - roog - parinz1234 + - seho-nl - Romain Geissler - Martin Auswöger - Adrien Moiruad @@ -2396,6 +2408,7 @@ The Symfony Connect username in parenthesis allows to get more information - Raphael Hardt - Ivan Nemets - Qingshan Luo + - Michael Olšavský - Ergie Gonzaga - Matthew J Mucklo - AnrDaemon @@ -2501,6 +2514,7 @@ The Symfony Connect username in parenthesis allows to get more information - Nicolas Badey (nico-b) - Olivier Scherler (oscherler) - Flo Gleixner (redflo) + - Romain Jacquart (romainjacquart) - Shane Preece (shane) - Stephan Wentz (temp) - Johannes Goslar @@ -2680,7 +2694,6 @@ The Symfony Connect username in parenthesis allows to get more information - Flinsch - Maciej Schmidt - botbotbot - - Cosmin Sandu - tatankat - Cláudio Cesar - Timon van der Vorm @@ -2846,7 +2859,6 @@ The Symfony Connect username in parenthesis allows to get more information - Boudry Julien - amcastror - Bram Van der Sype (brammm) - - roman joly (eltharin) - Guile (guile) - Mark Beech (jaybizzle) - Julien Moulin (lizjulien) @@ -2907,6 +2919,7 @@ The Symfony Connect username in parenthesis allows to get more information - J Bruni - Alexey Prilipko - vlakoff + - Anthony Tenneriello - thib92 - Yiorgos Kalligeros - Rudolf Ratusiński @@ -2923,6 +2936,7 @@ The Symfony Connect username in parenthesis allows to get more information - Frédéric G. Marand (fgm) - Freek Van der Herten (freekmurze) - Luca Genuzio (genuzio) + - Ben Gamra Housseine (hbgamra) - Andrew Marcinkevičius (ifdattic) - Ioana Hazsda (ioana-hazsda) - Jan Marek (janmarek) @@ -3175,13 +3189,11 @@ The Symfony Connect username in parenthesis allows to get more information - Olivier Laviale (olvlvl) - Pierre Gasté (pierre_g) - Pablo Monterde Perez (plebs) - - Jakub Podhorsky (podhy) - Pierre-Olivier Vares (povares) - Jimmy Leger (redpanda) - Ronny López (ronnylt) - Julius (sakalys) - Sébastien JEAN (sebastien76) - - Mokhtar Tlili (sf-djuba) - Dmitry (staratel) - Marcin Szepczynski (szepczynski) - Tito Miguel Costa (titomiguelcosta) @@ -3193,7 +3205,6 @@ The Symfony Connect username in parenthesis allows to get more information - Yorkie Chadwick (yorkie76) - Zakaria AMMOURA (zakariaamm) - Maxime Aknin (3m1x4m) - - Geordie - Pavel Barton - Exploit.cz - GuillaumeVerdon @@ -3203,7 +3214,6 @@ The Symfony Connect username in parenthesis allows to get more information - Youpie - Jason Stephens - srsbiz - - Tinjo Schöni - Taylan Kasap - Michael Orlitzky - Nicolas A. Bérard-Nault From f206376f48d11a8e94134a2edd3509adde92c515 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 28 Jun 2024 13:42:41 +0200 Subject: [PATCH 39/39] Update VERSION for 5.4.41 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0c4a13666d829..9a612d805283f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.41-DEV'; + public const VERSION = '5.4.41'; public const VERSION_ID = 50441; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; public const RELEASE_VERSION = 41; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025';