From 6ea76cafc273757d527edee5435e7809cc3ba9bf Mon Sep 17 00:00:00 2001 From: Santiago San Martin Date: Mon, 28 Apr 2025 21:14:38 -0300 Subject: [PATCH 01/57] Fix: exclude remember_me from security login authenticators --- .../Bundle/SecurityBundle/Security.php | 3 +- .../SecurityBundle/Tests/SecurityTest.php | 48 ++++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Security.php b/src/Symfony/Bundle/SecurityBundle/Security.php index acb30adba8adf..6b5286f2ea868 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security.php +++ b/src/Symfony/Bundle/SecurityBundle/Security.php @@ -188,8 +188,7 @@ private function getAuthenticator(?string $authenticatorName, string $firewallNa $firewallAuthenticatorLocator = $this->authenticators[$firewallName]; if (!$authenticatorName) { - $authenticatorIds = array_keys($firewallAuthenticatorLocator->getProvidedServices()); - + $authenticatorIds = array_filter(array_keys($firewallAuthenticatorLocator->getProvidedServices()), fn (string $authenticatorId) => $authenticatorId !== \sprintf('security.authenticator.remember_me.%s', $firewallName)); if (!$authenticatorIds) { throw new LogicException(sprintf('No authenticator was found for the firewall "%s".', $firewallName)); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php index 35bd329b2297e..c150730c2a8cb 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php @@ -155,7 +155,10 @@ public function testLogin() $firewallAuthenticatorLocator ->expects($this->once()) ->method('getProvidedServices') - ->willReturn(['security.authenticator.custom.dev' => $authenticator]) + ->willReturn([ + 'security.authenticator.custom.dev' => $authenticator, + 'security.authenticator.remember_me.main' => $authenticator + ]) ; $firewallAuthenticatorLocator ->expects($this->once()) @@ -274,6 +277,49 @@ public function testLoginWithoutRequestContext() $security->login($user); } + public function testLoginFailsWhenTooManyAuthenticatorsFound() + { + $request = new Request(); + $authenticator = $this->createMock(AuthenticatorInterface::class); + $requestStack = $this->createMock(RequestStack::class); + $firewallMap = $this->createMock(FirewallMap::class); + $firewall = new FirewallConfig('main', 'main'); + $userAuthenticator = $this->createMock(UserAuthenticatorInterface::class); + $user = $this->createMock(UserInterface::class); + $userChecker = $this->createMock(UserCheckerInterface::class); + + $container = $this->createMock(ContainerInterface::class); + $container + ->expects($this->atLeastOnce()) + ->method('get') + ->willReturnMap([ + ['request_stack', $requestStack], + ['security.firewall.map', $firewallMap], + ['security.authenticator.managers_locator', $this->createContainer('main', $userAuthenticator)], + ['security.user_checker_locator', $this->createContainer('main', $userChecker)], + ]) + ; + + $requestStack->expects($this->once())->method('getCurrentRequest')->willReturn($request); + $firewallMap->expects($this->once())->method('getFirewallConfig')->willReturn($firewall); + + $firewallAuthenticatorLocator = $this->createMock(ServiceProviderInterface::class); + $firewallAuthenticatorLocator + ->expects($this->once()) + ->method('getProvidedServices') + ->willReturn([ + 'security.authenticator.custom.main' => $authenticator, + 'security.authenticator.other.main' => $authenticator + ]) + ; + + $security = new Security($container, ['main' => $firewallAuthenticatorLocator]); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Too many authenticators were found for the current firewall "main". You must provide an instance of "Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface" to login programmatically. The available authenticators for the firewall "main" are "security.authenticator.custom.main" ,"security.authenticator.other.main'); + $security->login($user); + } + public function testLogout() { $request = new Request(); From f03e549086e1c2fd1bf1ef9752557e3ab7ec9617 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 10 May 2025 14:15:19 +0200 Subject: [PATCH 02/57] Bump Symfony version to 7.3.0 --- 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 d09c86966dbe2..b5a41236d1899 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -73,12 +73,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '7.3.0-BETA2'; + public const VERSION = '7.3.0-DEV'; public const VERSION_ID = 70300; public const MAJOR_VERSION = 7; public const MINOR_VERSION = 3; public const RELEASE_VERSION = 0; - public const EXTRA_VERSION = 'BETA2'; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '05/2025'; public const END_OF_LIFE = '01/2026'; From bcf20bc4f698c93581f8b4067c8ee3950fb737f2 Mon Sep 17 00:00:00 2001 From: Athorcis Date: Mon, 28 Apr 2025 13:34:00 +0200 Subject: [PATCH 03/57] [HttpFoundation] Fix: Encode path in X-Accel-Redirect header we need to encode the path in X-Accel-Redirect header, otherwise nginx fail when certain characters are present in it (like % or ?) https://github.com/rack/rack/issues/1306 --- .../Component/HttpFoundation/BinaryFileResponse.php | 2 +- .../HttpFoundation/Tests/BinaryFileResponseTest.php | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 41a244b818836..c22f283cba444 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -229,7 +229,7 @@ public function prepare(Request $request): static $path = $location.substr($path, \strlen($pathPrefix)); // Only set X-Accel-Redirect header if a valid URI can be produced // as nginx does not serve arbitrary file paths. - $this->headers->set($type, $path); + $this->headers->set($type, rawurlencode($path)); $this->maxlen = 0; break; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php index c7d47a4d70a35..8f298b77f7218 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php @@ -314,7 +314,15 @@ public function testXAccelMapping($realpath, $mapping, $virtual) $property->setValue($response, $file); $response->prepare($request); - $this->assertEquals($virtual, $response->headers->get('X-Accel-Redirect')); + $header = $response->headers->get('X-Accel-Redirect'); + + if ($virtual) { + // Making sure the path doesn't contain characters unsupported by nginx + $this->assertMatchesRegularExpression('/^([^?%]|%[0-9A-F]{2})*$/', $header); + $header = rawurldecode($header); + } + + $this->assertEquals($virtual, $header); } public function testDeleteFileAfterSend() @@ -361,6 +369,7 @@ public static function getSampleXAccelMappings() ['/home/Foo/bar.txt', '/var/www/=/files/,/home/Foo/=/baz/', '/baz/bar.txt'], ['/home/Foo/bar.txt', '"/var/www/"="/files/", "/home/Foo/"="/baz/"', '/baz/bar.txt'], ['/tmp/bar.txt', '"/var/www/"="/files/", "/home/Foo/"="/baz/"', null], + ['/var/www/var/www/files/foo%.txt', '/var/www/=/files/', '/files/var/www/files/foo%.txt'], ]; } From 0df0873e698de2a29d294ae857680f15090d8495 Mon Sep 17 00:00:00 2001 From: Santiago San Martin Date: Sun, 11 May 2025 19:35:25 -0300 Subject: [PATCH 04/57] fix(security): allow multiple Security attributes when applicable --- .../TraceableAccessDecisionManager.php | 2 +- .../TraceableAccessDecisionManagerTest.php | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php index a03e2d0ca749b..0ef062f6cc37d 100644 --- a/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php @@ -54,7 +54,7 @@ public function decide(TokenInterface $token, array $attributes, mixed $object = $this->accessDecisionStack[] = $accessDecision; try { - return $accessDecision->isGranted = $this->manager->decide($token, $attributes, $object, $accessDecision); + return $accessDecision->isGranted = $this->manager->decide($token, $attributes, $object, $accessDecision, $allowMultipleAttributes); } finally { $this->strategy = $accessDecision->strategy; $currentLog = array_pop($this->currentLog); diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php index f5313bb541c22..4bd9a01ac4097 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php @@ -11,12 +11,14 @@ namespace Symfony\Component\Security\Core\Tests\Authorization; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; +use Symfony\Component\Security\Core\Exception\InvalidArgumentException; use Symfony\Component\Security\Core\Tests\Fixtures\DummyVoter; class TraceableAccessDecisionManagerTest extends TestCase @@ -276,4 +278,48 @@ public function testCustomAccessDecisionManagerReturnsEmptyStrategy() $this->assertEquals('-', $adm->getStrategy()); } + + public function testThrowsExceptionWhenMultipleAttributesNotAllowed() + { + $accessDecisionManager = new AccessDecisionManager(); + $traceableAccessDecisionManager = new TraceableAccessDecisionManager($accessDecisionManager); + /** @var TokenInterface&MockObject $tokenMock */ + $tokenMock = $this->createMock(TokenInterface::class); + + $this->expectException(InvalidArgumentException::class); + $traceableAccessDecisionManager->decide($tokenMock, ['attr1', 'attr2']); + } + + /** + * @dataProvider allowMultipleAttributesProvider + */ + public function testAllowMultipleAttributes(array $attributes, bool $allowMultipleAttributes) + { + $accessDecisionManager = new AccessDecisionManager(); + $traceableAccessDecisionManager = new TraceableAccessDecisionManager($accessDecisionManager); + /** @var TokenInterface&MockObject $tokenMock */ + $tokenMock = $this->createMock(TokenInterface::class); + + $isGranted = $traceableAccessDecisionManager->decide($tokenMock, $attributes, null, null, $allowMultipleAttributes); + + $this->assertFalse($isGranted); + } + + public function allowMultipleAttributesProvider(): \Generator + { + yield [ + ['attr1'], + false, + ]; + + yield [ + ['attr1'], + true, + ]; + + yield [ + ['attr1', 'attr2', 'attr3'], + true, + ]; + } } From acc7563015718d2eff97f1096f0038a4b4ebe960 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 12 May 2025 09:26:05 +0200 Subject: [PATCH 05/57] fix lowest allowed Workflow component version --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index b3c81b28700a3..316c595ffa2bb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -108,7 +108,7 @@ "symfony/validator": "<6.4", "symfony/web-profiler-bundle": "<6.4", "symfony/webhook": "<7.2", - "symfony/workflow": "<7.3" + "symfony/workflow": "<7.3.0-beta2" }, "autoload": { "psr-4": { "Symfony\\Bundle\\FrameworkBundle\\": "" }, From c7206a95d15ef511c1a4371f9db25cc53ccc1999 Mon Sep 17 00:00:00 2001 From: Santiago San Martin Date: Wed, 23 Apr 2025 18:56:44 -0300 Subject: [PATCH 06/57] Fix: prevent "Cannot traverse an already closed generator" error by materializing Traversable input --- .../Serializer/Encoder/CsvEncoder.php | 4 ++++ .../Tests/Encoder/CsvEncoderTest.php | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php index 8f9c3cff0fb3c..07043d946d751 100644 --- a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php @@ -65,6 +65,10 @@ public function encode(mixed $data, string $format, array $context = []): string } elseif (empty($data)) { $data = [[]]; } else { + if ($data instanceof \Traversable) { + // Generators can only be iterated once — convert to array to allow multiple traversals + $data = iterator_to_array($data); + } // Sequential arrays of arrays are considered as collections $i = 0; foreach ($data as $key => $value) { diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php index c0be73a8bd685..cde6d333e99f0 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php @@ -710,4 +710,28 @@ public function testEndOfLinePassedInConstructor() $encoder = new CsvEncoder([CsvEncoder::END_OF_LINE => "\r\n"]); $this->assertSame("foo,bar\r\nhello,test\r\n", $encoder->encode($value, 'csv')); } + + /** @dataProvider provideIterable */ + public function testIterable(mixed $data) + { + $this->assertEquals(<<<'CSV' + foo,bar + hello,"hey ho" + hi,"let's go" + + CSV, $this->encoder->encode($data, 'csv')); + } + + public static function provideIterable() + { + $data = [ + ['foo' => 'hello', 'bar' => 'hey ho'], + ['foo' => 'hi', 'bar' => 'let\'s go'], + ]; + + yield 'array' => [$data]; + yield 'array iterator' => [new \ArrayIterator($data)]; + yield 'iterator aggregate' => [new \IteratorIterator(new \ArrayIterator($data))]; + yield 'generator' => [(fn (): \Generator => yield from $data)()]; + } } From ac859046995ac7c5070184ee88cb5b45696a7685 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 12 May 2025 10:58:22 +0200 Subject: [PATCH 07/57] use use statements instead of FQCNs --- .../DependencyInjection/FrameworkExtensionTestCase.php | 5 +++-- .../DependencyInjection/PhpFrameworkExtensionTest.php | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 1899d5239eb4d..990e1e8c252d4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -92,6 +92,7 @@ use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Webhook\Client\RequestParser; use Symfony\Component\Webhook\Controller\WebhookController; +use Symfony\Component\Workflow\DependencyInjection\WorkflowValidatorPass; use Symfony\Component\Workflow\Exception\InvalidDefinitionException; use Symfony\Component\Workflow\Metadata\InMemoryMetadataStore; use Symfony\Component\Workflow\WorkflowEvents; @@ -291,7 +292,7 @@ public function testWorkflows() DefinitionValidator::$called = false; $container = $this->createContainerFromFile('workflows', compile: false); - $container->addCompilerPass(new \Symfony\Component\Workflow\DependencyInjection\WorkflowValidatorPass()); + $container->addCompilerPass(new WorkflowValidatorPass()); $container->compile(); $this->assertTrue($container->hasDefinition('workflow.article'), 'Workflow is registered as a service'); @@ -410,7 +411,7 @@ public function testWorkflowAreValidated() $this->expectException(InvalidDefinitionException::class); $this->expectExceptionMessage('A transition from a place/state must have an unique name. Multiple transitions named "go" from place/state "first" were found on StateMachine "my_workflow".'); $container = $this->createContainerFromFile('workflow_not_valid', compile: false); - $container->addCompilerPass(new \Symfony\Component\Workflow\DependencyInjection\WorkflowValidatorPass()); + $container->addCompilerPass(new WorkflowValidatorPass()); $container->compile(); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index d2bd2b38eb313..f69a53932711c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -20,7 +20,10 @@ use Symfony\Component\RateLimiter\CompoundRateLimiterFactory; use Symfony\Component\RateLimiter\RateLimiterFactoryInterface; use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Workflow\Definition; +use Symfony\Component\Workflow\DependencyInjection\WorkflowValidatorPass; use Symfony\Component\Workflow\Exception\InvalidDefinitionException; +use Symfony\Component\Workflow\Validator\DefinitionValidatorInterface; class PhpFrameworkExtensionTest extends FrameworkExtensionTestCase { @@ -128,7 +131,7 @@ public function testWorkflowValidationStateMachine() ], ], ]); - $container->addCompilerPass(new \Symfony\Component\Workflow\DependencyInjection\WorkflowValidatorPass()); + $container->addCompilerPass(new WorkflowValidatorPass()); }); } @@ -456,13 +459,13 @@ public static function emailValidationModeProvider() } } -class WorkflowValidatorWithConstructor implements \Symfony\Component\Workflow\Validator\DefinitionValidatorInterface +class WorkflowValidatorWithConstructor implements DefinitionValidatorInterface { public function __construct(bool $enabled) { } - public function validate(\Symfony\Component\Workflow\Definition $definition, string $name): void + public function validate(Definition $definition, string $name): void { } } From 3e8c9b29164f639ef24f478ed9f16335621c3ba4 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Tue, 13 May 2025 09:45:01 +0200 Subject: [PATCH 08/57] [Security] Make data provider static --- .../Tests/Authorization/TraceableAccessDecisionManagerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php index 4bd9a01ac4097..496d970cd1f00 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/TraceableAccessDecisionManagerTest.php @@ -305,7 +305,7 @@ public function testAllowMultipleAttributes(array $attributes, bool $allowMultip $this->assertFalse($isGranted); } - public function allowMultipleAttributesProvider(): \Generator + public static function allowMultipleAttributesProvider(): \Generator { yield [ ['attr1'], From 9efc70222e92cc3134e607e4fd6152f97c898c26 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 4 May 2025 21:59:38 +0200 Subject: [PATCH 09/57] document the array shape of the content option --- .../Bridge/Mercure/MercureOptions.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Symfony/Component/Notifier/Bridge/Mercure/MercureOptions.php b/src/Symfony/Component/Notifier/Bridge/Mercure/MercureOptions.php index 4f3f80c0d7649..85a513cee6901 100644 --- a/src/Symfony/Component/Notifier/Bridge/Mercure/MercureOptions.php +++ b/src/Symfony/Component/Notifier/Bridge/Mercure/MercureOptions.php @@ -22,6 +22,21 @@ final class MercureOptions implements MessageOptionsInterface /** * @param string|string[]|null $topics + * @param array{ + * badge?: string, + * body?: string, + * data?: mixed, + * dir?: 'auto'|'ltr'|'rtl', + * icon?: string, + * image?: string, + * lang?: string, + * renotify?: bool, + * requireInteraction?: bool, + * silent?: bool, + * tag?: string, + * timestamp?: int, + * vibrate?: int|list, + * }|null $content */ public function __construct( string|array|null $topics = null, @@ -62,6 +77,23 @@ public function getRetry(): ?int return $this->retry; } + /** + * @return array{ + * badge?: string, + * body?: string, + * data?: mixed, + * dir?: 'auto'|'ltr'|'rtl', + * icon?: string, + * image?: string, + * lang?: string, + * renotify?: bool, + * requireInteraction?: bool, + * silent?: bool, + * tag?: string, + * timestamp?: int, + * vibrate?: int|list, + * }|null + */ public function getContent(): ?array { return $this->content; From 59a4ae92d2d6baeac7d9224041171c045ccfc63f Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Mon, 12 May 2025 15:44:05 -0400 Subject: [PATCH 10/57] [Console] Invokable command `#[Option]` adjustments - `#[Option] ?string $opt = null` as `VALUE_REQUIRED` - `#[Option] bool|string $opt = false` as `VALUE_OPTIONAL` - `#[Option] ?string $opt = ''` throws exception - allow `#[Option] ?array $opt = null` - more tests... --- .../Component/Console/Attribute/Option.php | 74 ++++++++++++----- .../Tests/Command/InvokableCommandTest.php | 79 +++++++++++++++---- 2 files changed, 118 insertions(+), 35 deletions(-) diff --git a/src/Symfony/Component/Console/Attribute/Option.php b/src/Symfony/Component/Console/Attribute/Option.php index 4aea4831e9ac6..19c82317033c4 100644 --- a/src/Symfony/Component/Console/Attribute/Option.php +++ b/src/Symfony/Component/Console/Attribute/Option.php @@ -22,6 +22,7 @@ class Option { private const ALLOWED_TYPES = ['string', 'bool', 'int', 'float', 'array']; + private const ALLOWED_UNION_TYPES = ['bool|string', 'bool|int', 'bool|float']; private string|bool|int|float|array|null $default = null; private array|\Closure $suggestedValues; @@ -56,18 +57,8 @@ public static function tryFrom(\ReflectionParameter $parameter): ?self return null; } - $type = $parameter->getType(); $name = $parameter->getName(); - - if (!$type instanceof \ReflectionNamedType) { - throw new LogicException(\sprintf('The parameter "$%s" must have a named type. Untyped, Union or Intersection types are not supported for command options.', $name)); - } - - $self->typeName = $type->getName(); - - if (!\in_array($self->typeName, self::ALLOWED_TYPES, true)) { - throw new LogicException(\sprintf('The type "%s" of parameter "$%s" is not supported as a command option. Only "%s" types are allowed.', $self->typeName, $name, implode('", "', self::ALLOWED_TYPES))); - } + $type = $parameter->getType(); if (!$parameter->isDefaultValueAvailable()) { throw new LogicException(\sprintf('The option parameter "$%s" must declare a default value.', $name)); @@ -80,16 +71,26 @@ public static function tryFrom(\ReflectionParameter $parameter): ?self $self->default = $parameter->getDefaultValue(); $self->allowNull = $parameter->allowsNull(); - if ('bool' === $self->typeName && $self->allowNull && \in_array($self->default, [true, false], true)) { - throw new LogicException(\sprintf('The option parameter "$%s" must not be nullable when it has a default boolean value.', $name)); + if ($type instanceof \ReflectionUnionType) { + return $self->handleUnion($type); } - if ('string' === $self->typeName && null === $self->default) { - throw new LogicException(\sprintf('The option parameter "$%s" must not have a default of null.', $name)); + if (!$type instanceof \ReflectionNamedType) { + throw new LogicException(\sprintf('The parameter "$%s" must have a named type. Untyped or Intersection types are not supported for command options.', $name)); } - if ('array' === $self->typeName && $self->allowNull) { - throw new LogicException(\sprintf('The option parameter "$%s" must not be nullable.', $name)); + $self->typeName = $type->getName(); + + if (!\in_array($self->typeName, self::ALLOWED_TYPES, true)) { + throw new LogicException(\sprintf('The type "%s" of parameter "$%s" is not supported as a command option. Only "%s" types are allowed.', $self->typeName, $name, implode('", "', self::ALLOWED_TYPES))); + } + + if ('bool' === $self->typeName && $self->allowNull && \in_array($self->default, [true, false], true)) { + throw new LogicException(\sprintf('The option parameter "$%s" must not be nullable when it has a default boolean value.', $name)); + } + + if ($self->allowNull && null !== $self->default) { + throw new LogicException(\sprintf('The option parameter "$%s" must either be not-nullable or have a default of null.', $name)); } if ('bool' === $self->typeName) { @@ -97,11 +98,10 @@ public static function tryFrom(\ReflectionParameter $parameter): ?self if (false !== $self->default) { $self->mode |= InputOption::VALUE_NEGATABLE; } + } elseif ('array' === $self->typeName) { + $self->mode = InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY; } else { - $self->mode = $self->allowNull ? InputOption::VALUE_OPTIONAL : InputOption::VALUE_REQUIRED; - if ('array' === $self->typeName) { - $self->mode |= InputOption::VALUE_IS_ARRAY; - } + $self->mode = InputOption::VALUE_REQUIRED; } if (\is_array($self->suggestedValues) && !\is_callable($self->suggestedValues) && 2 === \count($self->suggestedValues) && ($instance = $parameter->getDeclaringFunction()->getClosureThis()) && $instance::class === $self->suggestedValues[0] && \is_callable([$instance, $self->suggestedValues[1]])) { @@ -129,6 +129,14 @@ public function resolveValue(InputInterface $input): mixed { $value = $input->getOption($this->name); + if (null === $value && \in_array($this->typeName, self::ALLOWED_UNION_TYPES, true)) { + return true; + } + + if ('array' === $this->typeName && $this->allowNull && [] === $value) { + return null; + } + if ('bool' !== $this->typeName) { return $value; } @@ -139,4 +147,28 @@ public function resolveValue(InputInterface $input): mixed return $value ?? $this->default; } + + private function handleUnion(\ReflectionUnionType $type): self + { + $types = array_map( + static fn(\ReflectionType $t) => $t instanceof \ReflectionNamedType ? $t->getName() : null, + $type->getTypes(), + ); + + sort($types); + + $this->typeName = implode('|', array_filter($types)); + + if (!\in_array($this->typeName, self::ALLOWED_UNION_TYPES, true)) { + throw new LogicException(\sprintf('The union type for parameter "$%s" is not supported as a command option. Only "%s" types are allowed.', $this->name, implode('", "', self::ALLOWED_UNION_TYPES))); + } + + if (false !== $this->default) { + throw new LogicException(\sprintf('The option parameter "$%s" must have a default value of false.', $this->name)); + } + + $this->mode = InputOption::VALUE_OPTIONAL; + + return $this; + } } diff --git a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php index 88f1b78701e0a..917e2f88f1655 100644 --- a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php @@ -79,6 +79,7 @@ public function testCommandInputOptionDefinition() #[Option(shortcut: 'v')] bool $verbose = false, #[Option(description: 'User groups')] array $groups = [], #[Option(suggestedValues: [self::class, 'getSuggestedRoles'])] array $roles = ['ROLE_USER'], + #[Option] string|bool $opt = false, ): int { return 0; }); @@ -86,7 +87,8 @@ public function testCommandInputOptionDefinition() $timeoutInputOption = $command->getDefinition()->getOption('idle'); self::assertSame('idle', $timeoutInputOption->getName()); self::assertNull($timeoutInputOption->getShortcut()); - self::assertTrue($timeoutInputOption->isValueOptional()); + self::assertTrue($timeoutInputOption->isValueRequired()); + self::assertFalse($timeoutInputOption->isValueOptional()); self::assertFalse($timeoutInputOption->isNegatable()); self::assertNull($timeoutInputOption->getDefault()); @@ -120,6 +122,14 @@ public function testCommandInputOptionDefinition() self::assertTrue($rolesInputOption->hasCompletion()); $rolesInputOption->complete(new CompletionInput(), $suggestions = new CompletionSuggestions()); self::assertSame(['ROLE_ADMIN', 'ROLE_USER'], array_map(static fn (Suggestion $s) => $s->getValue(), $suggestions->getValueSuggestions())); + + $optInputOption = $command->getDefinition()->getOption('opt'); + self::assertSame('opt', $optInputOption->getName()); + self::assertNull($optInputOption->getShortcut()); + self::assertFalse($optInputOption->isValueRequired()); + self::assertTrue($optInputOption->isValueOptional()); + self::assertFalse($optInputOption->isNegatable()); + self::assertFalse($optInputOption->getDefault()); } public function testInvalidArgumentType() @@ -136,7 +146,7 @@ public function testInvalidArgumentType() public function testInvalidOptionType() { $command = new Command('foo'); - $command->setCode(function (#[Option] object $any) {}); + $command->setCode(function (#[Option] ?object $any = null) {}); $this->expectException(LogicException::class); $this->expectExceptionMessage('The type "object" of parameter "$any" is not supported as a command option. Only "string", "bool", "int", "float", "array" types are allowed.'); @@ -262,14 +272,30 @@ public function testNonBinaryInputOptions(array $parameters, array $expected) $command = new Command('foo'); $command->setCode(function ( #[Option] string $a = '', - #[Option] ?string $b = '', - #[Option] array $c = [], - #[Option] array $d = ['a', 'b'], + #[Option] array $b = [], + #[Option] array $c = ['a', 'b'], + #[Option] bool|string $d = false, + #[Option] ?string $e = null, + #[Option] ?array $f = null, + #[Option] int $g = 0, + #[Option] ?int $h = null, + #[Option] float $i = 0.0, + #[Option] ?float $j = null, + #[Option] bool|int $k = false, + #[Option] bool|float $l = false, ) use ($expected): int { $this->assertSame($expected[0], $a); $this->assertSame($expected[1], $b); $this->assertSame($expected[2], $c); $this->assertSame($expected[3], $d); + $this->assertSame($expected[4], $e); + $this->assertSame($expected[5], $f); + $this->assertSame($expected[6], $g); + $this->assertSame($expected[7], $h); + $this->assertSame($expected[8], $i); + $this->assertSame($expected[9], $j); + $this->assertSame($expected[10], $k); + $this->assertSame($expected[11], $l); return 0; }); @@ -279,9 +305,18 @@ public function testNonBinaryInputOptions(array $parameters, array $expected) public static function provideNonBinaryInputOptions(): \Generator { - yield 'defaults' => [[], ['', '', [], ['a', 'b']]]; - yield 'with-value' => [['--a' => 'x', '--b' => 'y', '--c' => ['z'], '--d' => ['c', 'd']], ['x', 'y', ['z'], ['c', 'd']]]; - yield 'without-value' => [['--b' => null], ['', null, [], ['a', 'b']]]; + yield 'defaults' => [ + [], + ['', [], ['a', 'b'], false, null, null, 0, null, 0.0, null, false, false], + ]; + yield 'with-value' => [ + ['--a' => 'x', '--b' => ['z'], '--c' => ['c', 'd'], '--d' => 'v', '--e' => 'w', '--f' => ['q'], '--g' => 1, '--h' => 2, '--i' => 3.1, '--j' => 4.2, '--k' => 5, '--l' => 6.3], + ['x', ['z'], ['c', 'd'], 'v', 'w', ['q'], 1, 2, 3.1, 4.2, 5, 6.3], + ]; + yield 'without-value' => [ + ['--d' => null, '--k' => null, '--l' => null], + ['', [], ['a', 'b'], true, null, null, 0, null, 0.0, null, true, true], + ]; } /** @@ -312,13 +347,29 @@ function (#[Option] ?bool $a = true) {}, function (#[Option] ?bool $a = false) {}, 'The option parameter "$a" must not be nullable when it has a default boolean value.', ]; - yield 'nullable-string' => [ - function (#[Option] ?string $a = null) {}, - 'The option parameter "$a" must not have a default of null.', + yield 'invalid-union-type' => [ + function (#[Option] array|bool $a = false) {}, + 'The union type for parameter "$a" is not supported as a command option. Only "bool|string", "bool|int", "bool|float" types are allowed.', + ]; + yield 'union-type-cannot-allow-null' => [ + function (#[Option] string|bool|null $a = null) {}, + 'The union type for parameter "$a" is not supported as a command option. Only "bool|string", "bool|int", "bool|float" types are allowed.', + ]; + yield 'union-type-default-true' => [ + function (#[Option] string|bool $a = true) {}, + 'The option parameter "$a" must have a default value of false.', + ]; + yield 'union-type-default-string' => [ + function (#[Option] string|bool $a = 'foo') {}, + 'The option parameter "$a" must have a default value of false.', + ]; + yield 'nullable-string-not-null-default' => [ + function (#[Option] ?string $a = 'foo') {}, + 'The option parameter "$a" must either be not-nullable or have a default of null.', ]; - yield 'nullable-array' => [ - function (#[Option] ?array $a = null) {}, - 'The option parameter "$a" must not be nullable.', + yield 'nullable-array-not-null-default' => [ + function (#[Option] ?array $a = []) {}, + 'The option parameter "$a" must either be not-nullable or have a default of null.', ]; } From 941c05187ab6ed54a464a16ac053b11f610dd9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Sun, 11 May 2025 20:09:09 +0200 Subject: [PATCH 11/57] [Config] Fix generated comment for multiline "info" --- .../Config/Builder/ConfigBuilderGenerator.php | 18 +++++++++--------- .../Builder/Fixtures/NodeInitialValues.php | 8 +++++++- .../Messenger/TransportsConfig.php | 3 +++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php b/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php index d43d814ebd38b..9649c8d82cbb9 100644 --- a/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php +++ b/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php @@ -413,39 +413,39 @@ private function getComment(BaseNode $node): string { $comment = ''; if ('' !== $info = (string) $node->getInfo()) { - $comment .= ' * '.$info."\n"; + $comment .= $info."\n"; } if (!$node instanceof ArrayNode) { foreach ((array) ($node->getExample() ?? []) as $example) { - $comment .= ' * @example '.$example."\n"; + $comment .= '@example '.$example."\n"; } if ('' !== $default = $node->getDefaultValue()) { - $comment .= ' * @default '.(null === $default ? 'null' : var_export($default, true))."\n"; + $comment .= '@default '.(null === $default ? 'null' : var_export($default, true))."\n"; } if ($node instanceof EnumNode) { - $comment .= sprintf(' * @param ParamConfigurator|%s $value', implode('|', array_unique(array_map(fn ($a) => !$a instanceof \UnitEnum ? var_export($a, true) : '\\'.ltrim(var_export($a, true), '\\'), $node->getValues()))))."\n"; + $comment .= sprintf('@param ParamConfigurator|%s $value', implode('|', array_unique(array_map(fn ($a) => !$a instanceof \UnitEnum ? var_export($a, true) : '\\'.ltrim(var_export($a, true), '\\'), $node->getValues()))))."\n"; } else { $parameterTypes = $this->getParameterTypes($node); - $comment .= ' * @param ParamConfigurator|'.implode('|', $parameterTypes).' $value'."\n"; + $comment .= '@param ParamConfigurator|'.implode('|', $parameterTypes).' $value'."\n"; } } else { foreach ((array) ($node->getExample() ?? []) as $example) { - $comment .= ' * @example '.json_encode($example)."\n"; + $comment .= '@example '.json_encode($example)."\n"; } if ($node->hasDefaultValue() && [] != $default = $node->getDefaultValue()) { - $comment .= ' * @default '.json_encode($default)."\n"; + $comment .= '@default '.json_encode($default)."\n"; } } if ($node->isDeprecated()) { - $comment .= ' * @deprecated '.$node->getDeprecation($node->getName(), $node->getParent()->getName())['message']."\n"; + $comment .= '@deprecated '.$node->getDeprecation($node->getName(), $node->getParent()->getName())['message']."\n"; } - return $comment; + return $comment ? ' * '.str_replace("\n", "\n * ", rtrim($comment, "\n"))."\n" : ''; } /** diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues.php index 153af57be9b5b..5c1259c20edd8 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues.php @@ -38,7 +38,13 @@ public function getConfigTreeBuilder(): TreeBuilder ->arrayPrototype() ->fixXmlConfig('option') ->children() - ->scalarNode('dsn')->end() + ->scalarNode('dsn') + ->info(<<<'INFO' + The DSN to use. This is a required option. + The info is used to describe the DSN, + it can be multi-line. + INFO) + ->end() ->scalarNode('serializer')->defaultNull()->end() ->arrayNode('options') ->normalizeKeys(false) diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/Messenger/TransportsConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/Messenger/TransportsConfig.php index b9d8b48db3556..6a98166eccc94 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/Messenger/TransportsConfig.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/NodeInitialValues/Symfony/Config/NodeInitialValues/Messenger/TransportsConfig.php @@ -16,6 +16,9 @@ class TransportsConfig private $_usedProperties = []; /** + * The DSN to use. This is a required option. + * The info is used to describe the DSN, + * it can be multi-line. * @default null * @param ParamConfigurator|mixed $value * @return $this From 594025893a06fbd451992204efab8e8301f74df0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 14 May 2025 09:14:36 +0200 Subject: [PATCH 12/57] remove no longer used service definition --- src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php index 7a3a95739b0f2..f1dc560ab76f8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/mailer.php @@ -45,7 +45,6 @@ tagged_iterator('mailer.transport_factory'), ]) - ->set('mailer.default_transport', TransportInterface::class) ->alias('mailer.default_transport', 'mailer.transports') ->alias(TransportInterface::class, 'mailer.default_transport') From 60cba4531731d74e98ff0395b2f1a9601b55e237 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Sat, 29 Mar 2025 18:18:47 +0100 Subject: [PATCH 13/57] [JsonPath] Add `JsonPathAssertionsTrait` and related constraints --- .../JsonPath/Test/JsonPathAssertionsTrait.php | 80 ++++++++ .../JsonPath/Test/JsonPathContains.php | 43 ++++ .../Component/JsonPath/Test/JsonPathCount.php | 40 ++++ .../JsonPath/Test/JsonPathEquals.php | 40 ++++ .../JsonPath/Test/JsonPathNotContains.php | 43 ++++ .../JsonPath/Test/JsonPathNotEquals.php | 40 ++++ .../JsonPath/Test/JsonPathNotSame.php | 40 ++++ .../Component/JsonPath/Test/JsonPathSame.php | 40 ++++ .../Test/JsonPathAssertionsTraitTest.php | 191 ++++++++++++++++++ 9 files changed, 557 insertions(+) create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathAssertionsTrait.php create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathContains.php create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathCount.php create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathEquals.php create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathNotContains.php create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathNotEquals.php create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathNotSame.php create mode 100644 src/Symfony/Component/JsonPath/Test/JsonPathSame.php create mode 100644 src/Symfony/Component/JsonPath/Tests/Test/JsonPathAssertionsTraitTest.php diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathAssertionsTrait.php b/src/Symfony/Component/JsonPath/Test/JsonPathAssertionsTrait.php new file mode 100644 index 0000000000000..42d35339a5760 --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathAssertionsTrait.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Assert; +use PHPUnit\Framework\ExpectationFailedException; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +trait JsonPathAssertionsTrait +{ + /** + * @throws ExpectationFailedException + */ + final public static function assertJsonPathEquals(mixed $expectedValue, JsonPath|string $jsonPath, string $json, string $message = ''): void + { + Assert::assertThat($expectedValue, new JsonPathEquals($jsonPath, $json), $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertJsonPathNotEquals(mixed $expectedValue, JsonPath|string $jsonPath, string $json, string $message = ''): void + { + Assert::assertThat($expectedValue, new JsonPathNotEquals($jsonPath, $json), $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertJsonPathCount(int $expectedCount, JsonPath|string $jsonPath, string $json, string $message = ''): void + { + Assert::assertThat($expectedCount, new JsonPathCount($jsonPath, $json), $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertJsonPathSame(mixed $expectedValue, JsonPath|string $jsonPath, string $json, string $message = ''): void + { + Assert::assertThat($expectedValue, new JsonPathSame($jsonPath, $json), $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertJsonPathNotSame(mixed $expectedValue, JsonPath|string $jsonPath, string $json, string $message = ''): void + { + Assert::assertThat($expectedValue, new JsonPathNotSame($jsonPath, $json), $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertJsonPathContains(mixed $expectedValue, JsonPath|string $jsonPath, string $json, bool $strict = true, string $message = ''): void + { + Assert::assertThat($expectedValue, new JsonPathContains($jsonPath, $json, $strict), $message); + } + + /** + * @throws ExpectationFailedException + */ + final public static function assertJsonPathNotContains(mixed $expectedValue, JsonPath|string $jsonPath, string $json, bool $strict = true, string $message = ''): void + { + Assert::assertThat($expectedValue, new JsonPathNotContains($jsonPath, $json, $strict), $message); + } +} diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathContains.php b/src/Symfony/Component/JsonPath/Test/JsonPathContains.php new file mode 100644 index 0000000000000..e043b90a40637 --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathContains.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\JsonPath\JsonCrawler; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +class JsonPathContains extends Constraint +{ + public function __construct( + private JsonPath|string $jsonPath, + private string $json, + private bool $strict = true, + ) { + } + + public function toString(): string + { + return \sprintf('is found in elements at JSON path "%s"', $this->jsonPath); + } + + protected function matches(mixed $other): bool + { + $result = (new JsonCrawler($this->json))->find($this->jsonPath); + + return \in_array($other, $result, $this->strict); + } +} diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathCount.php b/src/Symfony/Component/JsonPath/Test/JsonPathCount.php new file mode 100644 index 0000000000000..8c973a8309345 --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathCount.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\JsonPath\JsonCrawler; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +class JsonPathCount extends Constraint +{ + public function __construct( + private JsonPath|string $jsonPath, + private string $json, + ) { + } + + public function toString(): string + { + return \sprintf('matches expected count of JSON path "%s"', $this->jsonPath); + } + + protected function matches(mixed $other): bool + { + return $other === \count((new JsonCrawler($this->json))->find($this->jsonPath)); + } +} diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathEquals.php b/src/Symfony/Component/JsonPath/Test/JsonPathEquals.php new file mode 100644 index 0000000000000..56825434b5faa --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathEquals.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\JsonPath\JsonCrawler; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +class JsonPathEquals extends Constraint +{ + public function __construct( + private JsonPath|string $jsonPath, + private string $json, + ) { + } + + public function toString(): string + { + return \sprintf('equals JSON path "%s" result', $this->jsonPath); + } + + protected function matches(mixed $other): bool + { + return (new JsonCrawler($this->json))->find($this->jsonPath) == $other; + } +} diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathNotContains.php b/src/Symfony/Component/JsonPath/Test/JsonPathNotContains.php new file mode 100644 index 0000000000000..721d60fa29984 --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathNotContains.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\JsonPath\JsonCrawler; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +class JsonPathNotContains extends Constraint +{ + public function __construct( + private JsonPath|string $jsonPath, + private string $json, + private bool $strict = true, + ) { + } + + public function toString(): string + { + return \sprintf('is not found in elements at JSON path "%s"', $this->jsonPath); + } + + protected function matches(mixed $other): bool + { + $result = (new JsonCrawler($this->json))->find($this->jsonPath); + + return !\in_array($other, $result, $this->strict); + } +} diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathNotEquals.php b/src/Symfony/Component/JsonPath/Test/JsonPathNotEquals.php new file mode 100644 index 0000000000000..d149dbb59c441 --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathNotEquals.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\JsonPath\JsonCrawler; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +class JsonPathNotEquals extends Constraint +{ + public function __construct( + private JsonPath|string $jsonPath, + private string $json, + ) { + } + + public function toString(): string + { + return \sprintf('does not equal JSON path "%s" result', $this->jsonPath); + } + + protected function matches(mixed $other): bool + { + return (new JsonCrawler($this->json))->find($this->jsonPath) != $other; + } +} diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathNotSame.php b/src/Symfony/Component/JsonPath/Test/JsonPathNotSame.php new file mode 100644 index 0000000000000..248ac456fcbef --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathNotSame.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\JsonPath\JsonCrawler; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +class JsonPathNotSame extends Constraint +{ + public function __construct( + private JsonPath|string $jsonPath, + private string $json, + ) { + } + + public function toString(): string + { + return \sprintf('is not identical to JSON path "%s" result', $this->jsonPath); + } + + protected function matches(mixed $other): bool + { + return (new JsonCrawler($this->json))->find($this->jsonPath) !== $other; + } +} diff --git a/src/Symfony/Component/JsonPath/Test/JsonPathSame.php b/src/Symfony/Component/JsonPath/Test/JsonPathSame.php new file mode 100644 index 0000000000000..469922d8a0b90 --- /dev/null +++ b/src/Symfony/Component/JsonPath/Test/JsonPathSame.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\JsonPath\Test; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\JsonPath\JsonCrawler; +use Symfony\Component\JsonPath\JsonPath; + +/** + * @author Alexandre Daubois + * + * @experimental + */ +class JsonPathSame extends Constraint +{ + public function __construct( + private JsonPath|string $jsonPath, + private string $json, + ) { + } + + public function toString(): string + { + return \sprintf('is identical to JSON path "%s" result', $this->jsonPath); + } + + protected function matches(mixed $other): bool + { + return (new JsonCrawler($this->json))->find($this->jsonPath) === $other; + } +} diff --git a/src/Symfony/Component/JsonPath/Tests/Test/JsonPathAssertionsTraitTest.php b/src/Symfony/Component/JsonPath/Tests/Test/JsonPathAssertionsTraitTest.php new file mode 100644 index 0000000000000..62d64b53e1e8d --- /dev/null +++ b/src/Symfony/Component/JsonPath/Tests/Test/JsonPathAssertionsTraitTest.php @@ -0,0 +1,191 @@ +getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + public function testAssertJsonPathNotEqualsOk() + { + self::assertJsonPathNotEquals([2], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } + + public function testAssertJsonPathNotEqualsKo() + { + $thrown = false; + try { + self::assertJsonPathNotEquals([1], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } catch (AssertionFailedError $exception) { + self::assertMatchesRegularExpression('/Failed asserting that .+ does not equal JSON path "\$\.a\[2]" result./s', $exception->getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + public function testAssertJsonPathCountOk() + { + self::assertJsonPathCount(6, '$.a[*]', self::getSimpleCollectionCrawlerData()); + } + + public function testAssertJsonPathCountOkWithFilter() + { + self::assertJsonPathCount(2, '$.book[?(@.price > 25)]', <<getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + public function testAssertJsonPathSameOk() + { + self::assertJsonPathSame([1], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } + + public function testAssertJsonPathSameKo() + { + $thrown = false; + try { + self::assertJsonPathSame([2], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } catch (AssertionFailedError $exception) { + self::assertMatchesRegularExpression('/Failed asserting that .+ is identical to JSON path "\$\.a\[2]" result\./s', $exception->getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + public function testAssertJsonPathHasNoTypeCoercion() + { + $thrown = false; + try { + self::assertJsonPathSame(['1'], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } catch (AssertionFailedError $exception) { + self::assertMatchesRegularExpression('/Failed asserting that .+ is identical to JSON path "\$\.a\[2]" result\./s', $exception->getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + public function testAssertJsonPathNotSameOk() + { + self::assertJsonPathNotSame([2], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } + + public function testAssertJsonPathNotSameKo() + { + $thrown = false; + try { + self::assertJsonPathNotSame([1], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } catch (AssertionFailedError $exception) { + self::assertMatchesRegularExpression('/Failed asserting that .+ is not identical to JSON path "\$\.a\[2]" result\./s', $exception->getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + public function testAssertJsonPathNotSameHasNoTypeCoercion() + { + self::assertJsonPathNotSame(['1'], '$.a[2]', self::getSimpleCollectionCrawlerData()); + } + + public function testAssertJsonPathContainsOk() + { + self::assertJsonPathContains(1, '$.a[*]', self::getSimpleCollectionCrawlerData()); + } + + public function testAssertJsonPathContainsKo() + { + $thrown = false; + try { + self::assertJsonPathContains(0, '$.a[*]', self::getSimpleCollectionCrawlerData()); + } catch (AssertionFailedError $exception) { + self::assertSame('Failed asserting that 0 is found in elements at JSON path "$.a[*]".', $exception->getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + public function testAssertJsonPathNotContainsOk() + { + self::assertJsonPathNotContains(0, '$.a[*]', self::getSimpleCollectionCrawlerData()); + } + + public function testAssertJsonPathNotContainsKo() + { + $thrown = false; + try { + self::assertJsonPathNotContains(1, '$.a[*]', self::getSimpleCollectionCrawlerData()); + } catch (AssertionFailedError $exception) { + self::assertSame('Failed asserting that 1 is not found in elements at JSON path "$.a[*]".', $exception->getMessage()); + + $thrown = true; + } + + self::assertTrue($thrown); + } + + private static function getSimpleCollectionCrawlerData(): string + { + return << Date: Fri, 2 May 2025 14:12:20 +0200 Subject: [PATCH 14/57] [FrameworkBundle] skip messenger deduplication middlerware registration when no "default" lock is configured --- .../DependencyInjection/FrameworkExtension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 385a4caf38ded..fce6ba65c53ed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -569,9 +569,9 @@ public function load(array $configs, ContainerBuilder $container): void $container->removeDefinition('console.command.scheduler_debug'); } - // messenger depends on validation being registered + // messenger depends on validation, and lock being registered if ($messengerEnabled) { - $this->registerMessengerConfiguration($config['messenger'], $container, $loader, $this->readConfigEnabled('validation', $container, $config['validation']), $this->readConfigEnabled('lock', $container, $config['lock'])); + $this->registerMessengerConfiguration($config['messenger'], $container, $loader, $this->readConfigEnabled('validation', $container, $config['validation']), $this->readConfigEnabled('lock', $container, $config['lock']) && ($config['lock']['resources']['default'] ?? false)); } else { $container->removeDefinition('console.command.messenger_consume_messages'); $container->removeDefinition('console.command.messenger_stats'); From d12048430640bb2c83accae64a2cb38ea784adea Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 14 May 2025 12:40:11 +0200 Subject: [PATCH 15/57] normalize string values to a single ExposeSecurityLevel instance --- .../SecurityBundle/DependencyInjection/MainConfiguration.php | 2 +- .../Tests/DependencyInjection/MainConfigurationTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 9b7414de5e532..2b31b70a208bb 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -76,7 +76,7 @@ public function getConfigTreeBuilder(): TreeBuilder ->setDeprecated('symfony/security-bundle', '7.3', 'The "%node%" option is deprecated and will be removed in 8.0. Use the "expose_security_errors" option instead.') ->end() ->enumNode('expose_security_errors') - ->beforeNormalization()->ifString()->then(fn ($v) => ['value' => ExposeSecurityLevel::tryFrom($v)])->end() + ->beforeNormalization()->ifString()->then(fn ($v) => ExposeSecurityLevel::tryFrom($v))->end() ->values(ExposeSecurityLevel::cases()) ->defaultValue(ExposeSecurityLevel::None) ->end() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php index 6479e56a668e7..926abc5c7731c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php @@ -254,6 +254,9 @@ public static function provideHideUserNotFoundData(): iterable yield [['expose_security_errors' => ExposeSecurityLevel::None], ExposeSecurityLevel::None]; yield [['expose_security_errors' => ExposeSecurityLevel::AccountStatus], ExposeSecurityLevel::AccountStatus]; yield [['expose_security_errors' => ExposeSecurityLevel::All], ExposeSecurityLevel::All]; + yield [['expose_security_errors' => 'none'], ExposeSecurityLevel::None]; + yield [['expose_security_errors' => 'account_status'], ExposeSecurityLevel::AccountStatus]; + yield [['expose_security_errors' => 'all'], ExposeSecurityLevel::All]; } /** From 752b41de7450a2575937f2c70c9477e82eef2c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Tue, 13 May 2025 23:01:05 +0200 Subject: [PATCH 16/57] [TwigBundle] Improve error when autoconfiguring a class with both ExtensionInterface and Twig callable attribute --- .../Compiler/AttributeExtensionPass.php | 11 +++ .../Functional/AttributeExtensionTest.php | 76 +++++++++++++++---- 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/AttributeExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/AttributeExtensionPass.php index 24f760802bc94..354874866a0ae 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/AttributeExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/AttributeExtensionPass.php @@ -14,10 +14,13 @@ use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; use Twig\Attribute\AsTwigFilter; use Twig\Attribute\AsTwigFunction; use Twig\Attribute\AsTwigTest; +use Twig\Extension\AbstractExtension; use Twig\Extension\AttributeExtension; +use Twig\Extension\ExtensionInterface; /** * Register an instance of AttributeExtension for each service using the @@ -33,6 +36,14 @@ final class AttributeExtensionPass implements CompilerPassInterface public static function autoconfigureFromAttribute(ChildDefinition $definition, AsTwigFilter|AsTwigFunction|AsTwigTest $attribute, \ReflectionMethod $reflector): void { + $class = $reflector->getDeclaringClass(); + if ($class->implementsInterface(ExtensionInterface::class)) { + if ($class->isSubclassOf(AbstractExtension::class)) { + throw new LogicException(\sprintf('The class "%s" cannot extend "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.', $class->name, AbstractExtension::class, $attribute::class, $reflector->name)); + } + throw new LogicException(\sprintf('The class "%s" cannot implement "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.', $class->name, ExtensionInterface::class, $attribute::class, $reflector->name)); + } + $definition->addTag(self::TAG); // The service must be tagged as a runtime to call non-static methods diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php index 81ce2cbe97bca..8b4e4555f36a0 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php @@ -11,11 +11,15 @@ namespace Symfony\Bundle\TwigBundle\Tests\Functional; +use PHPUnit\Framework\Attributes\After; +use PHPUnit\Framework\Attributes\Before; +use PHPUnit\Framework\Attributes\BeforeClass; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\TwigBundle\Tests\TestCase; use Symfony\Bundle\TwigBundle\TwigBundle; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Kernel; use Twig\Attribute\AsTwigFilter; @@ -23,23 +27,23 @@ use Twig\Attribute\AsTwigTest; use Twig\Environment; use Twig\Error\RuntimeError; +use Twig\Extension\AbstractExtension; use Twig\Extension\AttributeExtension; class AttributeExtensionTest extends TestCase { - public function testExtensionWithAttributes() + /** @beforeClass */ + #[BeforeClass] + public static function assertTwigVersion(): void { if (!class_exists(AttributeExtension::class)) { self::markTestSkipped('Twig 3.21 is required.'); } + } - $kernel = new class('test', true) extends Kernel - { - public function registerBundles(): iterable - { - return [new FrameworkBundle(), new TwigBundle()]; - } - + public function testExtensionWithAttributes() + { + $kernel = new class extends AttributeExtensionKernel { public function registerContainerConfiguration(LoaderInterface $loader): void { $loader->load(static function (ContainerBuilder $container) { @@ -53,11 +57,6 @@ public function registerContainerConfiguration(LoaderInterface $loader): void $container->setAlias('twig_test', 'twig')->setPublic(true); }); } - - public function getProjectDir(): string - { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/AttributeExtension'; - } }; $kernel->boot(); @@ -73,10 +72,30 @@ public function getProjectDir(): string $twig->getRuntime(StaticExtensionWithAttributes::class); } + public function testInvalidExtensionClass() + { + $kernel = new class extends AttributeExtensionKernel { + public function registerContainerConfiguration(LoaderInterface $loader): void + { + $loader->load(static function (ContainerBuilder $container) { + $container->register(InvalidExtensionWithAttributes::class, InvalidExtensionWithAttributes::class) + ->setAutoconfigured(true); + }); + } + }; + + $this->expectException(LogicException::class); + $this->expectExceptionMessage('The class "Symfony\Bundle\TwigBundle\Tests\Functional\InvalidExtensionWithAttributes" cannot extend "Twig\Extension\AbstractExtension" and use the "#[Twig\Attribute\AsTwigFilter]" attribute on method "funFilter()", choose one or the other.'); + + $kernel->boot(); + } + + /** * @before * @after */ + #[Before, After] protected function deleteTempDir() { if (file_exists($dir = sys_get_temp_dir().'/'.Kernel::VERSION.'/AttributeExtension')) { @@ -85,6 +104,24 @@ protected function deleteTempDir() } } +abstract class AttributeExtensionKernel extends Kernel +{ + public function __construct() + { + parent::__construct('test', true); + } + + public function registerBundles(): iterable + { + return [new FrameworkBundle(), new TwigBundle()]; + } + + public function getProjectDir(): string + { + return sys_get_temp_dir().'/'.Kernel::VERSION.'/AttributeExtension'; + } +} + class StaticExtensionWithAttributes { #[AsTwigFilter('foo')] @@ -112,10 +149,19 @@ public function __construct(private bool $prefix) { } - #[AsTwigFilter('foo')] - #[AsTwigFunction('foo')] + #[AsTwigFilter('prefix_foo')] + #[AsTwigFunction('prefix_foo')] public function prefix(string $value): string { return $this->prefix.$value; } } + +class InvalidExtensionWithAttributes extends AbstractExtension +{ + #[AsTwigFilter('fun')] + public function funFilter(): string + { + return 'fun'; + } +} From 0c71a93e0bfc29e2dd47c785843ffa7a5406cc0c Mon Sep 17 00:00:00 2001 From: Vladimir Pakhomchik Date: Wed, 14 May 2025 12:41:00 +0200 Subject: [PATCH 17/57] Fixed lazy-loading ghost objects generation with property hooks with default values. --- .../Component/VarExporter/ProxyHelper.php | 2 +- .../LazyProxy/HookedWithDefaultValue.php | 16 +++++++++++++--- .../VarExporter/Tests/LazyGhostTraitTest.php | 12 +++++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/VarExporter/ProxyHelper.php b/src/Symfony/Component/VarExporter/ProxyHelper.php index e3a38b14a139b..862e0332a0ff8 100644 --- a/src/Symfony/Component/VarExporter/ProxyHelper.php +++ b/src/Symfony/Component/VarExporter/ProxyHelper.php @@ -80,7 +80,7 @@ public static function generateLazyGhost(\ReflectionClass $class): string .($p->isProtected() ? 'protected' : 'public') .($p->isProtectedSet() ? ' protected(set)' : '') ." {$type} \${$name}" - .($p->hasDefaultValue() ? ' = '.$p->getDefaultValue() : '') + .($p->hasDefaultValue() ? ' = '.VarExporter::export($p->getDefaultValue()) : '') ." {\n"; foreach ($p->getHooks() as $hook => $method) { diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/LazyProxy/HookedWithDefaultValue.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/LazyProxy/HookedWithDefaultValue.php index 1281109e7228d..7d49049ac449a 100644 --- a/src/Symfony/Component/VarExporter/Tests/Fixtures/LazyProxy/HookedWithDefaultValue.php +++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/LazyProxy/HookedWithDefaultValue.php @@ -4,8 +4,18 @@ class HookedWithDefaultValue { - public int $backedWithDefault = 321 { - get => $this->backedWithDefault; - set => $this->backedWithDefault = $value; + public int $backedIntWithDefault = 321 { + get => $this->backedIntWithDefault; + set => $this->backedIntWithDefault = $value; + } + + public string $backedStringWithDefault = '321' { + get => $this->backedStringWithDefault; + set => $this->backedStringWithDefault = $value; + } + + public bool $backedBoolWithDefault = false { + get => $this->backedBoolWithDefault; + set => $this->backedBoolWithDefault = $value; } } diff --git a/src/Symfony/Component/VarExporter/Tests/LazyGhostTraitTest.php b/src/Symfony/Component/VarExporter/Tests/LazyGhostTraitTest.php index 3f7513c270b5f..a80c007b53c87 100644 --- a/src/Symfony/Component/VarExporter/Tests/LazyGhostTraitTest.php +++ b/src/Symfony/Component/VarExporter/Tests/LazyGhostTraitTest.php @@ -516,16 +516,22 @@ public function testPropertyHooksWithDefaultValue() $initialized = true; }); - $this->assertSame(321, $object->backedWithDefault); + $this->assertSame(321, $object->backedIntWithDefault); + $this->assertSame('321', $object->backedStringWithDefault); + $this->assertSame(false, $object->backedBoolWithDefault); $this->assertTrue($initialized); $initialized = false; $object = $this->createLazyGhost(HookedWithDefaultValue::class, function ($instance) use (&$initialized) { $initialized = true; }); - $object->backedWithDefault = 654; + $object->backedIntWithDefault = 654; + $object->backedStringWithDefault = '654'; + $object->backedBoolWithDefault = true; $this->assertTrue($initialized); - $this->assertSame(654, $object->backedWithDefault); + $this->assertSame(654, $object->backedIntWithDefault); + $this->assertSame('654', $object->backedStringWithDefault); + $this->assertSame(true, $object->backedBoolWithDefault); } /** From 7dbe4bd2fc1b0351aad66feb04402395952e3941 Mon Sep 17 00:00:00 2001 From: Lauris Binde Date: Tue, 13 May 2025 18:57:21 +0200 Subject: [PATCH 18/57] [Validator] Review Latvian translations --- .../Validator/Resources/translations/validators.lv.xlf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf index db61de4f486d5..d16d43bf8a7e6 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf @@ -468,11 +468,11 @@ This value is not a valid slug. - Šī vērtība nav derīgs slug. + Šī vērtība nav derīgs URL slug. This value is not a valid Twig template. - This value is not a valid Twig template. + Šī vērtība nav derīgs Twig šablons. From f758e2677a619333c064bd7de4a7054606d2c0cf Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 15 May 2025 09:08:55 +0200 Subject: [PATCH 19/57] forbid to use "hide_user_not_found" and "expose_security_errors" at the same time "hide_user_not_found" will not have any effect if "expose_security_errors" is set. Throwing an exception early will improve DX and avoid WTF moments where one might be wondering why the "hide_user_not_found" option doesn't change anything. --- .../DependencyInjection/MainConfiguration.php | 4 ++++ .../DependencyInjection/MainConfigurationTest.php | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 2b31b70a208bb..0a2d32c9f3f4d 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -59,6 +59,10 @@ public function getConfigTreeBuilder(): TreeBuilder ->beforeNormalization() ->always() ->then(function ($v) { + if (isset($v['hide_user_not_found']) && isset($v['expose_security_errors'])) { + throw new InvalidConfigurationException('You cannot use both "hide_user_not_found" and "expose_security_errors" at the same time.'); + } + if (isset($v['hide_user_not_found']) && !isset($v['expose_security_errors'])) { $v['expose_security_errors'] = $v['hide_user_not_found'] ? ExposeSecurityLevel::None : ExposeSecurityLevel::All; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php index 926abc5c7731c..6904a21b18113 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php @@ -283,4 +283,18 @@ public static function provideHideUserNotFoundLegacyData(): iterable yield [['hide_user_not_found' => true], ExposeSecurityLevel::None, true]; yield [['hide_user_not_found' => false], ExposeSecurityLevel::All, false]; } + + public function testCannotUseHideUserNotFoundAndExposeSecurityErrorsAtTheSameTime() + { + $processor = new Processor(); + $configuration = new MainConfiguration([], []); + + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('You cannot use both "hide_user_not_found" and "expose_security_errors" at the same time.'); + + $processor->processConfiguration($configuration, [static::$minimalConfig + [ + 'hide_user_not_found' => true, + 'expose_security_errors' => ExposeSecurityLevel::None, + ]]); + } } From 6174d091cc605e6e0c1770e41bc89304f4eb130f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 15 May 2025 15:18:10 +0200 Subject: [PATCH 20/57] [DependencyInjection] Fix missing binding for ServiceCollectionInterface when declaring a service subscriber --- .../Compiler/RegisterServiceSubscribersPass.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php index 87470c39894e4..89b822bc53b44 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php @@ -20,6 +20,7 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; use Symfony\Contracts\Service\Attribute\SubscribedService; +use Symfony\Contracts\Service\ServiceCollectionInterface; use Symfony\Contracts\Service\ServiceProviderInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; @@ -134,6 +135,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed $value->setBindings([ PsrContainerInterface::class => new BoundArgument($locatorRef, false), ServiceProviderInterface::class => new BoundArgument($locatorRef, false), + ServiceCollectionInterface::class => new BoundArgument($locatorRef, false), ] + $value->getBindings()); return parent::processValue($value); From fc10d48fdf6598e491bbb256ed990cd5f8f9e452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 15 May 2025 17:29:37 +0200 Subject: [PATCH 21/57] [WebLink] Hint that prerender is deprecated --- src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php | 8 ++++++-- src/Symfony/Component/WebLink/Link.php | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php b/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php index 11eca517c5d69..c8640a4ea5f00 100644 --- a/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/WebLinkExtension.php @@ -46,7 +46,7 @@ public function getFunctions(): array /** * Adds a "Link" HTTP header. * - * @param string $rel The relation type (e.g. "preload", "prefetch", "prerender" or "dns-prefetch") + * @param string $rel The relation type (e.g. "preload", "prefetch", or "dns-prefetch") * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") * * @return string The relation URI @@ -117,7 +117,11 @@ public function prefetch(string $uri, array $attributes = []): string } /** - * Indicates to the client that it should prerender this resource . + * Indicates to the client that it should prerender this resource. + * + * This feature is deprecated and superseded by the Speculation Rules API. + * + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/prerender * * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") * diff --git a/src/Symfony/Component/WebLink/Link.php b/src/Symfony/Component/WebLink/Link.php index 5eab61346e925..ebad518efb170 100644 --- a/src/Symfony/Component/WebLink/Link.php +++ b/src/Symfony/Component/WebLink/Link.php @@ -98,6 +98,12 @@ class Link implements EvolvableLinkInterface public const REL_PREDECESSOR_VERSION = 'predecessor-version'; public const REL_PREFETCH = 'prefetch'; public const REL_PRELOAD = 'preload'; + + /** + * This feature is deprecated and superseded by the Speculation Rules API. + * + * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/prerender + */ public const REL_PRERENDER = 'prerender'; public const REL_PREV = 'prev'; public const REL_PREVIEW = 'preview'; From 193b69c18a66858981b42b68b7691237aabacc0b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 16 May 2025 10:43:03 +0200 Subject: [PATCH 22/57] simplify Webhook constraint --- src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json b/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json index 259fb81e9bcae..0b1907fb71f15 100644 --- a/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/Smsbox/composer.json @@ -31,7 +31,7 @@ "symfony/polyfill-php83": "^1.28" }, "require-dev": { - "symfony/webhook": "^6.4|^7.0|^7.2" + "symfony/webhook": "^6.4|^7.0" }, "autoload": { "psr-4": { From d51f563ed3c0d6029c2219620e91fb4cf3088b1d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 15 May 2025 09:25:30 +0200 Subject: [PATCH 23/57] let the SlugValidator accept AsciiSlugger results --- .../Component/Validator/Constraints/Slug.php | 2 +- .../Tests/Constraints/SlugValidatorTest.php | 19 ++++++++++++++++--- src/Symfony/Component/Validator/composer.json | 1 + 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/Slug.php b/src/Symfony/Component/Validator/Constraints/Slug.php index 52a5d94c2d93b..55d847ccb618b 100644 --- a/src/Symfony/Component/Validator/Constraints/Slug.php +++ b/src/Symfony/Component/Validator/Constraints/Slug.php @@ -25,7 +25,7 @@ class Slug extends Constraint public const NOT_SLUG_ERROR = '14e6df1e-c8ab-4395-b6ce-04b132a3765e'; public string $message = 'This value is not a valid slug.'; - public string $regex = '/^[a-z0-9]+(?:-[a-z0-9]+)*$/'; + public string $regex = '/^[a-z0-9]+(?:-[a-z0-9]+)*$/i'; #[HasNamedArguments] public function __construct( diff --git a/src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php index e8d210b8377e3..f88bff3e167ef 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use Symfony\Component\String\Slugger\AsciiSlugger; use Symfony\Component\Validator\Constraints\Slug; use Symfony\Component\Validator\Constraints\SlugValidator; use Symfony\Component\Validator\Exception\UnexpectedValueException; @@ -47,6 +48,7 @@ public function testExpectsStringCompatibleType() * @testWith ["test-slug"] * ["slug-123-test"] * ["slug"] + * ["TestSlug"] */ public function testValidSlugs($slug) { @@ -56,8 +58,7 @@ public function testValidSlugs($slug) } /** - * @testWith ["NotASlug"] - * ["Not a slug"] + * @testWith ["Not a slug"] * ["not-á-slug"] * ["not-@-slug"] */ @@ -91,7 +92,7 @@ public function testCustomRegexInvalidSlugs($slug) /** * @testWith ["slug"] - * @testWith ["test1234"] + * ["test1234"] */ public function testCustomRegexValidSlugs($slug) { @@ -101,4 +102,16 @@ public function testCustomRegexValidSlugs($slug) $this->assertNoViolation(); } + + /** + * @testWith ["PHP"] + * ["Symfony is cool"] + * ["Lorem ipsum dolor sit amet"] + */ + public function testAcceptAsciiSluggerResults(string $text) + { + $this->validator->validate((new AsciiSlugger())->slug($text), new Slug()); + + $this->assertNoViolation(); + } } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 5177d37d2955a..0eaac5f6bf735 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -38,6 +38,7 @@ "symfony/mime": "^6.4|^7.0", "symfony/property-access": "^6.4|^7.0", "symfony/property-info": "^6.4|^7.0", + "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4.3|^7.0.3", "symfony/type-info": "^7.1", "egulias/email-validator": "^2.1.10|^3|^4" From 85ef2a31d4e4afaa1e7240d1d8639c0ec351c0be Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 16 May 2025 11:31:49 +0200 Subject: [PATCH 24/57] add test for DatePointType converting database string to PHP value --- .../Bridge/Doctrine/Tests/Types/DatePointTypeTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php index 6900de3f168b9..84b265ed6502c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Types/DatePointTypeTest.php @@ -76,6 +76,14 @@ public function testDateTimeImmutableConvertsToPHPValue() $this->assertSame($expected->format($format), $actual->format($format)); } + public function testDatabaseValueConvertsToPHPValue() + { + $actual = $this->type->convertToPHPValue('2025-03-03 12:13:14', new PostgreSQLPlatform()); + + $this->assertInstanceOf(DatePoint::class, $actual); + $this->assertSame('2025-03-03 12:13:14', $actual->format('Y-m-d H:i:s')); + } + public function testGetName() { $this->assertSame('date_point', $this->type->getName()); From 88b322e144d380f61e0182a242e6e2a4efdcb9d7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 16 May 2025 15:57:08 +0200 Subject: [PATCH 25/57] [FrameworkBundle] Fix declaring fiel-attr tags in xml config files --- .../DependencyInjection/Configuration.php | 1 + .../Resources/config/schema/symfony-1.0.xsd | 2 +- .../Fixtures/php/form_csrf_field_attr.php | 22 +++++++++++++++++++ ...ield_name.xml => form_csrf_field_attr.xml} | 8 ++++++- .../form_csrf_under_form_sets_field_name.xml | 15 ------------- .../Fixtures/yml/form_csrf_field_attr.yml | 16 ++++++++++++++ .../FrameworkExtensionTestCase.php | 11 ++++++++++ 7 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_csrf_field_attr.php rename src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/{form_csrf_sets_field_name.xml => form_csrf_field_attr.xml} (67%) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_csrf_field_attr.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 50c093f28f17e..5154393f2769e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -252,6 +252,7 @@ private function addFormSection(ArrayNodeDefinition $rootNode, callable $enableI ->arrayNode('field_attr') ->performNoDeepMerging() ->normalizeKeys(false) + ->useAttributeAsKey('name') ->scalarPrototype()->end() ->defaultValue(['data-controller' => 'csrf-protection']) ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 491cd1e4ffb7c..e99022acf7c45 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -79,7 +79,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_csrf_field_attr.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_csrf_field_attr.php new file mode 100644 index 0000000000000..103ee4797a1b8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/form_csrf_field_attr.php @@ -0,0 +1,22 @@ +loadFromExtension('framework', [ + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], + 'csrf_protection' => [ + 'enabled' => true, + ], + 'form' => [ + 'csrf_protection' => [ + 'field-attr' => [ + 'data-foo' => 'bar', + 'data-bar' => 'baz', + ], + ], + ], + 'session' => [ + 'storage_factory_id' => 'session.storage.factory.native', + ], +]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_sets_field_name.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_field_attr.xml similarity index 67% rename from src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_sets_field_name.xml rename to src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_field_attr.xml index 4a05e9d33294e..1889703bec2a9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_sets_field_name.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_field_attr.xml @@ -9,7 +9,13 @@ - + + + + bar + baz + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml deleted file mode 100644 index 09ef0ee167eb4..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/form_csrf_under_form_sets_field_name.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_csrf_field_attr.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_csrf_field_attr.yml new file mode 100644 index 0000000000000..db519977548c4 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/form_csrf_field_attr.yml @@ -0,0 +1,16 @@ +framework: + annotations: false + http_method_override: false + handle_all_throwables: true + php_errors: + log: true + csrf_protection: + enabled: true + form: + csrf_protection: + enabled: true + field_attr: + data-foo: bar + data-bar: baz + session: + storage_factory_id: session.storage.factory.native diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 7bf66512d2b2b..655f9180eceb2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1413,6 +1413,17 @@ public function testFormsCanBeEnabledWithoutCsrfProtection() $this->assertFalse($container->getParameter('form.type_extension.csrf.enabled')); } + public function testFormCsrfFieldAttr() + { + $container = $this->createContainerFromFile('form_csrf_field_attr'); + + $expected = [ + 'data-foo' => 'bar', + 'data-bar' => 'baz', + ]; + $this->assertSame($expected, $container->getParameter('form.type_extension.csrf.field_attr')); + } + public function testStopwatchEnabledWithDebugModeEnabled() { $container = $this->createContainerFromFile('default_config', [ From 72171c0543e3e84b70e6bc0ff1ef6373f254c917 Mon Sep 17 00:00:00 2001 From: matlec Date: Wed, 14 May 2025 19:55:19 +0200 Subject: [PATCH 26/57] [DependencyInjection] Make `DefinitionErrorExceptionPass` consider `IGNORE_ON_UNINITIALIZED_REFERENCE` and `RUNTIME_EXCEPTION_ON_INVALID_REFERENCE` the same --- .../Compiler/DefinitionErrorExceptionPass.php | 5 ++++- .../Tests/Compiler/DefinitionErrorExceptionPassTest.php | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php index b6a2cf907ee9b..204401cd2c8ee 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php @@ -65,7 +65,10 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed } if ($value instanceof Reference && $this->currentId !== $targetId = (string) $value) { - if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { + if ( + ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() + || ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() + ) { $this->sourceReferences[$targetId][$this->currentId] ??= true; } else { $this->sourceReferences[$targetId][$this->currentId] = false; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php index 9ab5c27fcf763..5ed7be315114a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php @@ -64,6 +64,9 @@ public function testSkipNestedErrors() $container->register('foo', 'stdClass') ->addArgument(new Reference('bar', ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)); + $container->register('baz', 'stdClass') + ->addArgument(new Reference('bar', ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE)); + $pass = new DefinitionErrorExceptionPass(); $pass->process($container); From 032a5770d623448300ea2a0768b2c5841b1c8a30 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 17 May 2025 18:06:41 +0200 Subject: [PATCH 27/57] Provide missing translations thanks to Gemini --- .../Validator/Resources/translations/validators.af.xlf | 2 +- .../Validator/Resources/translations/validators.ar.xlf | 2 +- .../Validator/Resources/translations/validators.az.xlf | 2 +- .../Validator/Resources/translations/validators.be.xlf | 2 +- .../Validator/Resources/translations/validators.bg.xlf | 2 +- .../Validator/Resources/translations/validators.bs.xlf | 2 +- .../Validator/Resources/translations/validators.ca.xlf | 2 +- .../Validator/Resources/translations/validators.cs.xlf | 2 +- .../Validator/Resources/translations/validators.cy.xlf | 2 +- .../Validator/Resources/translations/validators.da.xlf | 2 +- .../Validator/Resources/translations/validators.el.xlf | 2 +- .../Validator/Resources/translations/validators.es.xlf | 2 +- .../Validator/Resources/translations/validators.et.xlf | 2 +- .../Validator/Resources/translations/validators.eu.xlf | 2 +- .../Validator/Resources/translations/validators.fa.xlf | 2 +- .../Validator/Resources/translations/validators.fi.xlf | 2 +- .../Validator/Resources/translations/validators.fr.xlf | 2 +- .../Validator/Resources/translations/validators.gl.xlf | 2 +- .../Validator/Resources/translations/validators.he.xlf | 2 +- .../Validator/Resources/translations/validators.hr.xlf | 2 +- .../Validator/Resources/translations/validators.hu.xlf | 2 +- .../Validator/Resources/translations/validators.hy.xlf | 2 +- .../Validator/Resources/translations/validators.id.xlf | 2 +- .../Validator/Resources/translations/validators.it.xlf | 2 +- .../Validator/Resources/translations/validators.ja.xlf | 2 +- .../Validator/Resources/translations/validators.lb.xlf | 2 +- .../Validator/Resources/translations/validators.lt.xlf | 2 +- .../Validator/Resources/translations/validators.mk.xlf | 2 +- .../Validator/Resources/translations/validators.mn.xlf | 2 +- .../Validator/Resources/translations/validators.my.xlf | 2 +- .../Validator/Resources/translations/validators.nb.xlf | 2 +- .../Validator/Resources/translations/validators.nl.xlf | 2 +- .../Validator/Resources/translations/validators.nn.xlf | 2 +- .../Validator/Resources/translations/validators.no.xlf | 2 +- .../Validator/Resources/translations/validators.pt.xlf | 2 +- .../Validator/Resources/translations/validators.pt_BR.xlf | 2 +- .../Validator/Resources/translations/validators.ro.xlf | 2 +- .../Validator/Resources/translations/validators.ru.xlf | 2 +- .../Validator/Resources/translations/validators.sk.xlf | 2 +- .../Validator/Resources/translations/validators.sl.xlf | 2 +- .../Validator/Resources/translations/validators.sq.xlf | 2 +- .../Validator/Resources/translations/validators.sr_Cyrl.xlf | 2 +- .../Validator/Resources/translations/validators.sr_Latn.xlf | 2 +- .../Validator/Resources/translations/validators.sv.xlf | 2 +- .../Validator/Resources/translations/validators.th.xlf | 2 +- .../Validator/Resources/translations/validators.tl.xlf | 2 +- .../Validator/Resources/translations/validators.tr.xlf | 2 +- .../Validator/Resources/translations/validators.uk.xlf | 2 +- .../Validator/Resources/translations/validators.ur.xlf | 2 +- .../Validator/Resources/translations/validators.uz.xlf | 2 +- .../Validator/Resources/translations/validators.vi.xlf | 2 +- .../Validator/Resources/translations/validators.zh_CN.xlf | 2 +- .../Validator/Resources/translations/validators.zh_TW.xlf | 2 +- 53 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf index de23860799dc6..270f85355e82f 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Hierdie waarde is nie 'n geldige Twig-sjabloon nie. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf index f1792bb427644..8e068ef17429d 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + هذه القيمة ليست نموذج Twig صالح. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf index ab15702b6f30a..8721507fbe97b 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Bu dəyər etibarlı Twig şablonu deyil. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf index 5f4448d1b433e..aa0e67bd8c2fc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Гэта значэнне не з'яўляецца сапраўдным шаблонам Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf index 333187eef9826..4717830d50925 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Тази стойност не е валиден Twig шаблон. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf index e27274a36f216..46a6aa049e04a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ova vrijednost nije važeći Twig šablon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf index 5506b4672974b..15d047c31a9fc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Aquest valor no és una plantilla Twig vàlida. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf index 87a03badd9f15..c4fd950203c21 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Tato hodnota není platná šablona Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf index 98e481b67b70d..0fc87d313fbe2 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Nid yw'r gwerth hwn yn dempled Twig dilys. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf index 976ee850e4325..eabf4450f34f5 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Denne værdi er ikke en gyldig Twig-skabelon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf index fe490aacddb40..d8298f530b58d 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Αυτή η τιμή δεν είναι έγκυρο πρότυπο Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf index 2bd3433990ded..b428fd8c19463 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Este valor no es una plantilla Twig válida. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf index 1317d41955a47..bbc0b5692b043 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + See väärtus ei ole kehtiv Twig'i mall. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf index f92ab9638581f..d5be082cd4043 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Balio hau ez da Twig txantiloi baliozko bat. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf index 73a97fb3cae28..cc8b3d8f0a135 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + این مقدار یک قالب معتبر Twig نیست. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf index 044beb1c44cc4..714a7a08b81e8 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Tämä arvo ei ole kelvollinen Twig-malli. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index 07953955b92d5..fe92eb2e76aef 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Cette valeur n'est pas un modèle Twig valide. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf index c85e942f36040..1b2303774119f 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Este valor non é un modelo Twig válido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf index 8a985737485b4..ec792b699bdf5 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + ערך זה אינו תבנית Twig חוקית. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf index 10985f3df18a8..17a4c88f105b0 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ova vrijednost nije valjani Twig predložak. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf index 2a3472dd94a2d..39e3acac818bc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ez az érték nem érvényes Twig sablon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf index 0c3953a27dc29..a1dbb93b419a3 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Այս արժեքը վավեր Twig ձևանմուշ չէ: diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf index 7c8a3c8dfb808..669a2afa5efd2 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Nilai ini bukan templat Twig yang valid. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf index 5258cf7d3ec7a..102cbc9beb7cd 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Questo valore non è un template Twig valido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf index ae0e734b45c67..fe928e89604a0 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + この値は有効な Twig テンプレートではありません。 diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf index 2961aec0b0ef2..81bd7de6f717e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Dëse Wäert ass kee valabelen Twig-Template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf index 9c56c8377cdd8..f9e9f9e220d21 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ši reikšmė nėra tinkamas „Twig“ šablonas. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf index 7d9a63dbd7e36..6c39949aa1e09 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Оваа вредност не е валиден Twig шаблон. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf index 222526fe24b19..b3ee44b43b417 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Энэ утга нь Twig-ийн хүчинтэй загвар биш юм. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf index 90b6648acc594..e82ab3b19c8e1 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + ဤတန်ဖိုးသည် မှန်ကန်သော Twig တင်းပလိတ်မဟုတ်ပါ။ diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf index 0997c1af56a14..b0281532b4c61 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Denne verdien er ikke en gyldig Twig-mal. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf index 820bb69aae42e..10086869427df 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Deze waarde is geen geldige Twig-template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf index 6a36a1cc2571f..6cb8812b596f1 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Denne verdien er ikkje ein gyldig Twig-mal. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf index 0997c1af56a14..b0281532b4c61 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Denne verdien er ikke en gyldig Twig-mal. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf index 0d685d524cd69..5732702d7bcde 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Este valor não é um modelo Twig válido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf index 3dbdd4ea2d675..a755b2363a314 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Este valor não é um modelo Twig válido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf index bed709ceaf927..56d20634736e7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Această valoare nu este un șablon Twig valid. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index 5fc8d14d833ae..dff7ecbbb84c6 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Это значение не является допустимым шаблоном Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf index 253b4cd8c37d1..c8d9d912a1750 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Táto hodnota nie je platná šablóna Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf index 669d8e85d8a5c..b4cc222ad74d3 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ta vrednost ni veljavna predloga Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf index 1933143261af8..7ae80b937a37c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf @@ -481,7 +481,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Kjo vlerë nuk është një shabllon Twig i vlefshëm. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf index d36e83ca62785..fa355e47664bc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ова вредност није важећи Twig шаблон. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf index ba9092a1c0c4c..61704f6eaaf12 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ova vrednost nije važeći Twig šablon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf index 8ed255071e270..c88ffc5823278 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Det här värdet är inte en giltig Twig-mall. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf index de5008674af45..26371cd6a8bf7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + ค่านี้ไม่ใช่เทมเพลต Twig ที่ถูกต้อง diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf index 310a7a20563ae..ef1e2ad845caf 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Ang halagang ito ay hindi isang balidong Twig template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf index 0bf57d80b7ca4..2cf33ab33c7af 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Bu değer geçerli bir Twig şablonu değil. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf index 2110eb48e7dfe..eb4a0db9ec6d0 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Це значення не є дійсним шаблоном Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf index 280b1488d2cf8..6a28566ca062e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + یہ قدر ایک درست Twig سانچہ نہیں ہے۔ diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf index da07805f689c2..b54fee24a3cdf 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Bu qiymat yaroqli Twig shabloni emas. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf index 048be7f2c4336..8bc1e4c3e078d 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + Giá trị này không phải là một mẫu Twig hợp lệ. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf index 24a89c15b8b91..ff41473e1555e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + 此值不是有效的 Twig 模板。 diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf index 783461efa4c7f..7c44889bf8724 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - This value is not a valid Twig template. + 此值不是有效的 Twig 模板。 From 388e97f48ef2a01010778a972ef5e2b723df043c Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Sat, 17 May 2025 18:49:07 +0200 Subject: [PATCH 28/57] Update Mailer Azure bridge API docs link --- src/Symfony/Component/Mailer/Bridge/Azure/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Azure/README.md b/src/Symfony/Component/Mailer/Bridge/Azure/README.md index acd9cc25abb53..36b81fccfa385 100644 --- a/src/Symfony/Component/Mailer/Bridge/Azure/README.md +++ b/src/Symfony/Component/Mailer/Bridge/Azure/README.md @@ -21,8 +21,8 @@ where: Resources --------- - * [Microsoft Azure (ACS) Email API Docs](https://learn.microsoft.com/en-us/rest/api/communication/dataplane/email/send) + * [Microsoft Azure (ACS) Email API Docs](https://learn.microsoft.com/en-us/rest/api/communication/email/email/send) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) - in the [main Symfony repository](https://github.com/symfony/symfony) \ No newline at end of file + in the [main Symfony repository](https://github.com/symfony/symfony) From 5789965374fc8052fd7448cfb0024250a1cfc820 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Mon, 19 May 2025 10:27:13 +0200 Subject: [PATCH 29/57] Revert Slug constraint This commit reverts #58542. --- src/Symfony/Component/Validator/CHANGELOG.md | 1 - .../Component/Validator/Constraints/Slug.php | 42 ------- .../Validator/Constraints/SlugValidator.php | 47 ------- .../Validator/Tests/Constraints/SlugTest.php | 47 ------- .../Tests/Constraints/SlugValidatorTest.php | 117 ------------------ 5 files changed, 254 deletions(-) delete mode 100644 src/Symfony/Component/Validator/Constraints/Slug.php delete mode 100644 src/Symfony/Component/Validator/Constraints/SlugValidator.php delete mode 100644 src/Symfony/Component/Validator/Tests/Constraints/SlugTest.php delete mode 100644 src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index ae1ae20da804d..a7363d7f59c19 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -8,7 +8,6 @@ CHANGELOG * Deprecate defining custom constraints not supporting named arguments * Deprecate passing an array of options to the constructors of the constraint classes, pass each option as a dedicated argument instead * Add support for ratio checks for SVG files to the `Image` constraint - * Add the `Slug` constraint * Add support for the `otherwise` option in the `When` constraint * Add support for multiple fields containing nested constraints in `Composite` constraints * Add the `stopOnFirstError` option to the `Unique` constraint to validate all elements diff --git a/src/Symfony/Component/Validator/Constraints/Slug.php b/src/Symfony/Component/Validator/Constraints/Slug.php deleted file mode 100644 index 55d847ccb618b..0000000000000 --- a/src/Symfony/Component/Validator/Constraints/Slug.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Constraints; - -use Symfony\Component\Validator\Attribute\HasNamedArguments; -use Symfony\Component\Validator\Constraint; - -/** - * Validates that a value is a valid slug. - * - * @author Raffaele Carelle - */ -#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] -class Slug extends Constraint -{ - public const NOT_SLUG_ERROR = '14e6df1e-c8ab-4395-b6ce-04b132a3765e'; - - public string $message = 'This value is not a valid slug.'; - public string $regex = '/^[a-z0-9]+(?:-[a-z0-9]+)*$/i'; - - #[HasNamedArguments] - public function __construct( - ?string $regex = null, - ?string $message = null, - ?array $groups = null, - mixed $payload = null, - ) { - parent::__construct([], $groups, $payload); - - $this->message = $message ?? $this->message; - $this->regex = $regex ?? $this->regex; - } -} diff --git a/src/Symfony/Component/Validator/Constraints/SlugValidator.php b/src/Symfony/Component/Validator/Constraints/SlugValidator.php deleted file mode 100644 index b914cad31b466..0000000000000 --- a/src/Symfony/Component/Validator/Constraints/SlugValidator.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Constraints; - -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\ConstraintValidator; -use Symfony\Component\Validator\Exception\UnexpectedTypeException; -use Symfony\Component\Validator\Exception\UnexpectedValueException; - -/** - * @author Raffaele Carelle - */ -class SlugValidator extends ConstraintValidator -{ - public function validate(mixed $value, Constraint $constraint): void - { - if (!$constraint instanceof Slug) { - throw new UnexpectedTypeException($constraint, Slug::class); - } - - if (null === $value || '' === $value) { - return; - } - - if (!\is_scalar($value) && !$value instanceof \Stringable) { - throw new UnexpectedValueException($value, 'string'); - } - - $value = (string) $value; - - if (0 === preg_match($constraint->regex, $value)) { - $this->context->buildViolation($constraint->message) - ->setParameter('{{ value }}', $this->formatValue($value)) - ->setCode(Slug::NOT_SLUG_ERROR) - ->addViolation(); - } - } -} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/SlugTest.php b/src/Symfony/Component/Validator/Tests/Constraints/SlugTest.php deleted file mode 100644 index a2c5b07d3f873..0000000000000 --- a/src/Symfony/Component/Validator/Tests/Constraints/SlugTest.php +++ /dev/null @@ -1,47 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Constraints; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Validator\Constraints\Slug; -use Symfony\Component\Validator\Mapping\ClassMetadata; -use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; - -class SlugTest extends TestCase -{ - public function testAttributes() - { - $metadata = new ClassMetadata(SlugDummy::class); - $loader = new AttributeLoader(); - self::assertTrue($loader->loadClassMetadata($metadata)); - - [$bConstraint] = $metadata->properties['b']->getConstraints(); - self::assertSame('myMessage', $bConstraint->message); - self::assertSame(['Default', 'SlugDummy'], $bConstraint->groups); - - [$cConstraint] = $metadata->properties['c']->getConstraints(); - self::assertSame(['my_group'], $cConstraint->groups); - self::assertSame('some attached data', $cConstraint->payload); - } -} - -class SlugDummy -{ - #[Slug] - private $a; - - #[Slug(message: 'myMessage')] - private $b; - - #[Slug(groups: ['my_group'], payload: 'some attached data')] - private $c; -} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php deleted file mode 100644 index f88bff3e167ef..0000000000000 --- a/src/Symfony/Component/Validator/Tests/Constraints/SlugValidatorTest.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Constraints; - -use Symfony\Component\String\Slugger\AsciiSlugger; -use Symfony\Component\Validator\Constraints\Slug; -use Symfony\Component\Validator\Constraints\SlugValidator; -use Symfony\Component\Validator\Exception\UnexpectedValueException; -use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; - -class SlugValidatorTest extends ConstraintValidatorTestCase -{ - protected function createValidator(): SlugValidator - { - return new SlugValidator(); - } - - public function testNullIsValid() - { - $this->validator->validate(null, new Slug()); - - $this->assertNoViolation(); - } - - public function testEmptyStringIsValid() - { - $this->validator->validate('', new Slug()); - - $this->assertNoViolation(); - } - - public function testExpectsStringCompatibleType() - { - $this->expectException(UnexpectedValueException::class); - $this->validator->validate(new \stdClass(), new Slug()); - } - - /** - * @testWith ["test-slug"] - * ["slug-123-test"] - * ["slug"] - * ["TestSlug"] - */ - public function testValidSlugs($slug) - { - $this->validator->validate($slug, new Slug()); - - $this->assertNoViolation(); - } - - /** - * @testWith ["Not a slug"] - * ["not-á-slug"] - * ["not-@-slug"] - */ - public function testInvalidSlugs($slug) - { - $constraint = new Slug(message: 'myMessage'); - - $this->validator->validate($slug, $constraint); - - $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"'.$slug.'"') - ->setCode(Slug::NOT_SLUG_ERROR) - ->assertRaised(); - } - - /** - * @testWith ["test-slug", true] - * ["slug-123-test", true] - */ - public function testCustomRegexInvalidSlugs($slug) - { - $constraint = new Slug(regex: '/^[a-z0-9]+$/i'); - - $this->validator->validate($slug, $constraint); - - $this->buildViolation($constraint->message) - ->setParameter('{{ value }}', '"'.$slug.'"') - ->setCode(Slug::NOT_SLUG_ERROR) - ->assertRaised(); - } - - /** - * @testWith ["slug"] - * ["test1234"] - */ - public function testCustomRegexValidSlugs($slug) - { - $constraint = new Slug(regex: '/^[a-z0-9]+$/i'); - - $this->validator->validate($slug, $constraint); - - $this->assertNoViolation(); - } - - /** - * @testWith ["PHP"] - * ["Symfony is cool"] - * ["Lorem ipsum dolor sit amet"] - */ - public function testAcceptAsciiSluggerResults(string $text) - { - $this->validator->validate((new AsciiSlugger())->slug($text), new Slug()); - - $this->assertNoViolation(); - } -} From 357e5f82f90885411015a9d00c5a3d7e98c54b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 19 May 2025 11:05:46 +0200 Subject: [PATCH 30/57] [Validator] Review "twig template" translation --- .../Validator/Resources/translations/validators.fr.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index fe92eb2e76aef..6c45f32237b52 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - Cette valeur n'est pas un modèle Twig valide. + Cette valeur n'est pas un modèle Twig valide. From 4817c589724bdfde15ad4d97442dee8bd97b6d54 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Mon, 19 May 2025 13:11:22 +0200 Subject: [PATCH 31/57] [Validator] Review Croatian translation --- .../Validator/Resources/translations/validators.hr.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf index 17a4c88f105b0..5b891d79f3ddd 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf @@ -472,7 +472,7 @@ This value is not a valid Twig template. - Ova vrijednost nije valjani Twig predložak. + Ova vrijednost nije valjani Twig predložak. From c29f02688f77b7908e2e2835e4dbe5d3bf711a77 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 19 May 2025 08:45:42 +0200 Subject: [PATCH 32/57] add missing $extensions and $extensionsMessage to the Image constraint --- .../Component/Validator/Constraints/Image.php | 14 +++- .../Tests/Constraints/ImageValidatorTest.php | 73 +++++++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/Image.php b/src/Symfony/Component/Validator/Constraints/Image.php index 43590f4f2425c..8fafa5044f201 100644 --- a/src/Symfony/Component/Validator/Constraints/Image.php +++ b/src/Symfony/Component/Validator/Constraints/Image.php @@ -64,7 +64,7 @@ class Image extends File */ protected static $errorNames = self::ERROR_NAMES; - public $mimeTypes = 'image/*'; + public $mimeTypes; public $minWidth; public $maxWidth; public $maxHeight; @@ -140,7 +140,9 @@ public function __construct( ?string $allowPortraitMessage = null, ?string $corruptedMessage = null, ?array $groups = null, - mixed $payload = null + mixed $payload = null, + array|string|null $extensions = null, + ?string $extensionsMessage = null, ) { parent::__construct( $options, @@ -163,7 +165,9 @@ public function __construct( $uploadExtensionErrorMessage, $uploadErrorMessage, $groups, - $payload + $payload, + $extensions, + $extensionsMessage, ); $this->minWidth = $minWidth ?? $this->minWidth; @@ -192,6 +196,10 @@ public function __construct( $this->allowPortraitMessage = $allowPortraitMessage ?? $this->allowPortraitMessage; $this->corruptedMessage = $corruptedMessage ?? $this->corruptedMessage; + if (null === $this->mimeTypes && [] === $this->extensions) { + $this->mimeTypes = 'image/*'; + } + if (!\in_array('image/*', (array) $this->mimeTypes, true) && !\array_key_exists('mimeTypesMessage', $options ?? []) && null === $mimeTypesMessage) { $this->mimeTypesMessage = 'The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}.'; } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php index 3e646cfa39572..c8341e95f0176 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Validator\Tests\Constraints; +use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\Mime\MimeTypes; use Symfony\Component\Validator\Constraints\Image; use Symfony\Component\Validator\Constraints\ImageValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -579,4 +581,75 @@ public static function provideInvalidMimeTypeWithNarrowedSet() ]), ]; } + + /** + * @dataProvider providerValidExtension + */ + public function testExtensionValid(string $name) + { + if (!class_exists(MimeTypes::class)) { + $this->markTestSkipped('Guessing the mime type is not possible'); + } + + $constraint = new Image(mimeTypes: [], extensions: ['gif'], extensionsMessage: 'myMessage'); + + $this->validator->validate(new File(__DIR__.'/Fixtures/'.$name), $constraint); + + $this->assertNoViolation(); + } + + public static function providerValidExtension(): iterable + { + yield ['test.gif']; + yield ['test.png.gif']; + } + + /** + * @dataProvider provideInvalidExtension + */ + public function testExtensionInvalid(string $name, string $extension) + { + $path = __DIR__.'/Fixtures/'.$name; + $constraint = new Image(extensions: ['png', 'svg'], extensionsMessage: 'myMessage'); + + $this->validator->validate(new File($path), $constraint); + + $this->buildViolation('myMessage') + ->setParameters([ + '{{ file }}' => '"'.$path.'"', + '{{ extension }}' => '"'.$extension.'"', + '{{ extensions }}' => '"png", "svg"', + '{{ name }}' => '"'.$name.'"', + ]) + ->setCode(Image::INVALID_EXTENSION_ERROR) + ->assertRaised(); + } + + public static function provideInvalidExtension(): iterable + { + yield ['test.gif', 'gif']; + yield ['test.png.gif', 'gif']; + } + + public function testExtensionAutodetectMimeTypesInvalid() + { + if (!class_exists(MimeTypes::class)) { + $this->markTestSkipped('Guessing the mime type is not possible'); + } + + $path = __DIR__.'/Fixtures/invalid-content.gif'; + $constraint = new Image(mimeTypesMessage: 'myMessage', extensions: ['gif']); + + $this->validator->validate(new File($path), $constraint); + + $this->buildViolation('myMessage') + ->setParameters([ + '{{ file }}' => '"'.$path.'"', + '{{ name }}' => '"invalid-content.gif"', + '{{ type }}' => '"text/plain"', + '{{ types }}' => '"image/gif"', + ]) + ->setCode(Image::INVALID_MIME_TYPE_ERROR) + ->assertRaised(); + } } From 42eb1c0b2fc37b643a86a8a3417cdbec26620ae6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 20 May 2025 08:06:46 +0200 Subject: [PATCH 33/57] Remove translations for slug validation error --- .../Validator/Resources/translations/validators.af.xlf | 4 ---- .../Validator/Resources/translations/validators.ar.xlf | 4 ---- .../Validator/Resources/translations/validators.az.xlf | 4 ---- .../Validator/Resources/translations/validators.be.xlf | 4 ---- .../Validator/Resources/translations/validators.bg.xlf | 4 ---- .../Validator/Resources/translations/validators.bs.xlf | 4 ---- .../Validator/Resources/translations/validators.ca.xlf | 4 ---- .../Validator/Resources/translations/validators.cs.xlf | 4 ---- .../Validator/Resources/translations/validators.cy.xlf | 4 ---- .../Validator/Resources/translations/validators.da.xlf | 4 ---- .../Validator/Resources/translations/validators.de.xlf | 4 ---- .../Validator/Resources/translations/validators.el.xlf | 4 ---- .../Validator/Resources/translations/validators.en.xlf | 4 ---- .../Validator/Resources/translations/validators.es.xlf | 4 ---- .../Validator/Resources/translations/validators.et.xlf | 4 ---- .../Validator/Resources/translations/validators.eu.xlf | 4 ---- .../Validator/Resources/translations/validators.fa.xlf | 4 ---- .../Validator/Resources/translations/validators.fi.xlf | 4 ---- .../Validator/Resources/translations/validators.fr.xlf | 4 ---- .../Validator/Resources/translations/validators.gl.xlf | 4 ---- .../Validator/Resources/translations/validators.he.xlf | 4 ---- .../Validator/Resources/translations/validators.hr.xlf | 4 ---- .../Validator/Resources/translations/validators.hu.xlf | 4 ---- .../Validator/Resources/translations/validators.hy.xlf | 4 ---- .../Validator/Resources/translations/validators.id.xlf | 4 ---- .../Validator/Resources/translations/validators.it.xlf | 4 ---- .../Validator/Resources/translations/validators.ja.xlf | 4 ---- .../Validator/Resources/translations/validators.lb.xlf | 4 ---- .../Validator/Resources/translations/validators.lt.xlf | 4 ---- .../Validator/Resources/translations/validators.lv.xlf | 4 ---- .../Validator/Resources/translations/validators.mk.xlf | 4 ---- .../Validator/Resources/translations/validators.mn.xlf | 4 ---- .../Validator/Resources/translations/validators.my.xlf | 4 ---- .../Validator/Resources/translations/validators.nb.xlf | 4 ---- .../Validator/Resources/translations/validators.nl.xlf | 4 ---- .../Validator/Resources/translations/validators.nn.xlf | 4 ---- .../Validator/Resources/translations/validators.no.xlf | 4 ---- .../Validator/Resources/translations/validators.pl.xlf | 4 ---- .../Validator/Resources/translations/validators.pt.xlf | 4 ---- .../Validator/Resources/translations/validators.pt_BR.xlf | 4 ---- .../Validator/Resources/translations/validators.ro.xlf | 4 ---- .../Validator/Resources/translations/validators.ru.xlf | 4 ---- .../Validator/Resources/translations/validators.sk.xlf | 4 ---- .../Validator/Resources/translations/validators.sl.xlf | 4 ---- .../Validator/Resources/translations/validators.sq.xlf | 4 ---- .../Validator/Resources/translations/validators.sr_Cyrl.xlf | 4 ---- .../Validator/Resources/translations/validators.sr_Latn.xlf | 4 ---- .../Validator/Resources/translations/validators.sv.xlf | 4 ---- .../Validator/Resources/translations/validators.th.xlf | 4 ---- .../Validator/Resources/translations/validators.tl.xlf | 4 ---- .../Validator/Resources/translations/validators.tr.xlf | 4 ---- .../Validator/Resources/translations/validators.uk.xlf | 4 ---- .../Validator/Resources/translations/validators.ur.xlf | 4 ---- .../Validator/Resources/translations/validators.uz.xlf | 4 ---- .../Validator/Resources/translations/validators.vi.xlf | 4 ---- .../Validator/Resources/translations/validators.zh_CN.xlf | 4 ---- .../Validator/Resources/translations/validators.zh_TW.xlf | 4 ---- 57 files changed, 228 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf index 270f85355e82f..9f53b1afe35c3 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.af.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Hierdie waarde mag nie na week "{{ max }}" kom nie. - - This value is not a valid slug. - Hierdie waarde is nie 'n geldige slug nie. - This value is not a valid Twig template. Hierdie waarde is nie 'n geldige Twig-sjabloon nie. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf index 8e068ef17429d..827eed1bcc86e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ar.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". يجب ألا تكون هذه القيمة بعد الأسبوع "{{ max }}". - - This value is not a valid slug. - هذه القيمة ليست رمزا صالحا. - This value is not a valid Twig template. هذه القيمة ليست نموذج Twig صالح. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf index 8721507fbe97b..9332c9ec2fd93 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.az.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Bu dəyər "{{ max }}" həftəsindən sonra olmamalıdır. - - This value is not a valid slug. - Bu dəyər etibarlı slug deyil. - This value is not a valid Twig template. Bu dəyər etibarlı Twig şablonu deyil. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf index aa0e67bd8c2fc..7308820465dfa 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Гэта значэнне не павінна быць пасля тыдня "{{ max }}". - - This value is not a valid slug. - Гэта значэнне не з'яўляецца сапраўдным слугам. - This value is not a valid Twig template. Гэта значэнне не з'яўляецца сапраўдным шаблонам Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf index 4717830d50925..afd7590f51cb9 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.bg.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Тази стойност не трябва да бъде след седмица "{{ max }}". - - This value is not a valid slug. - Тази стойност не е валиден слаг. - This value is not a valid Twig template. Тази стойност не е валиден Twig шаблон. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf index 46a6aa049e04a..d6b7de5768ee5 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.bs.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ova vrijednost ne bi trebala biti nakon sedmice "{{ max }}". - - This value is not a valid slug. - Ova vrijednost nije važeći slug. - This value is not a valid Twig template. Ova vrijednost nije važeći Twig šablon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf index 15d047c31a9fc..d656ef540f825 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ca.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Aquest valor no ha de ser posterior a la setmana "{{ max }}". - - This value is not a valid slug. - Aquest valor no és un slug vàlid. - This value is not a valid Twig template. Aquest valor no és una plantilla Twig vàlida. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf index c4fd950203c21..2a2e559b95238 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Tato hodnota by neměla být týden za "{{ max }}". - - This value is not a valid slug. - Tato hodnota není platný slug. - This value is not a valid Twig template. Tato hodnota není platná šablona Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf index 0fc87d313fbe2..08a76667d5f4a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cy.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ni ddylai'r gwerth hwn fod ar ôl yr wythnos "{{ max }}". - - This value is not a valid slug. - Nid yw'r gwerth hwn yn slug dilys. - This value is not a valid Twig template. Nid yw'r gwerth hwn yn dempled Twig dilys. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf index eabf4450f34f5..bb05bba2e641c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.da.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Denne værdi bør ikke være efter uge "{{ max }}". - - This value is not a valid slug. - Denne værdi er ikke en gyldig slug. - This value is not a valid Twig template. Denne værdi er ikke en gyldig Twig-skabelon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf index 7320d3de53dfe..f02c56c6c5ca9 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Dieser Wert darf nicht nach der Woche "{{ max }}" sein. - - This value is not a valid slug. - Dieser Wert ist kein gültiger Slug. - This value is not a valid Twig template. Dieser Wert ist kein valides Twig-Template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf index d8298f530b58d..9aec12ff82ce7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Αυτή η τιμή δεν πρέπει να είναι μετά την εβδομάδα "{{ max }}". - - This value is not a valid slug. - Αυτή η τιμή δεν είναι έγκυρο slug. - This value is not a valid Twig template. Αυτή η τιμή δεν είναι έγκυρο πρότυπο Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index cad8466103fa8..f8c664f18c423 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". This value should not be after week "{{ max }}". - - This value is not a valid slug. - This value is not a valid slug. - This value is not a valid Twig template. This value is not a valid Twig template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf index b428fd8c19463..a9ad8a76b11e9 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.es.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Este valor no debe ser posterior a la semana "{{ max }}". - - This value is not a valid slug. - Este valor no es un slug válido. - This value is not a valid Twig template. Este valor no es una plantilla Twig válida. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf index bbc0b5692b043..2375aa4ade30c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". See väärtus ei tohiks olla pärast nädalat "{{ max }}". - - This value is not a valid slug. - See väärtus ei ole kehtiv slug. - This value is not a valid Twig template. See väärtus ei ole kehtiv Twig'i mall. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf index d5be082cd4043..830f8673dff94 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.eu.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Balio hau ez luke astearen "{{ max }}" ondoren egon behar. - - This value is not a valid slug. - Balio hau ez da slug balioduna. - This value is not a valid Twig template. Balio hau ez da Twig txantiloi baliozko bat. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf index cc8b3d8f0a135..f47633fd4a624 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fa.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". این مقدار نباید بعد از هفته "{{ max }}" باشد. - - This value is not a valid slug. - این مقدار یک slug معتبر نیست. - This value is not a valid Twig template. این مقدار یک قالب معتبر Twig نیست. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf index 714a7a08b81e8..c046963f7ec66 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fi.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Tämän arvon ei pitäisi olla viikon "{{ max }}" jälkeen. - - This value is not a valid slug. - Tämä arvo ei ole kelvollinen slug. - This value is not a valid Twig template. Tämä arvo ei ole kelvollinen Twig-malli. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index 6c45f32237b52..13033c01973c8 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Cette valeur ne doit pas être postérieure à la semaine "{{ max }}". - - This value is not a valid slug. - Cette valeur n'est pas un slug valide. - This value is not a valid Twig template. Cette valeur n'est pas un modèle Twig valide. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf index 1b2303774119f..391d741e96564 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.gl.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Este valor non debe estar despois da semana "{{ max }}". - - This value is not a valid slug. - Este valor non é un slug válido. - This value is not a valid Twig template. Este valor non é un modelo Twig válido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf index ec792b699bdf5..671a98881536e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.he.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". ערך זה לא אמור להיות לאחר שבוע "{{ max }}". - - This value is not a valid slug. - ערך זה אינו slug חוקי. - This value is not a valid Twig template. ערך זה אינו תבנית Twig חוקית. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf index 5b891d79f3ddd..0951d41926514 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hr.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ova vrijednost ne bi trebala biti nakon tjedna "{{ max }}". - - This value is not a valid slug. - Ova vrijednost nije valjani slug. - This value is not a valid Twig template. Ova vrijednost nije valjani Twig predložak. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf index 39e3acac818bc..dffab0ccbf700 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hu.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ez az érték nem lehet a "{{ max }}". hétnél későbbi. - - This value is not a valid slug. - Ez az érték nem érvényes slug. - This value is not a valid Twig template. Ez az érték nem érvényes Twig sablon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf index a1dbb93b419a3..856babbd5fe4e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.hy.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Այս արժեքը չպետք է լինի «{{ max }}» շաբաթից հետո։ - - This value is not a valid slug. - Այս արժեքը վավեր slug չէ: - This value is not a valid Twig template. Այս արժեքը վավեր Twig ձևանմուշ չէ: diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf index 669a2afa5efd2..b9796f888f924 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Nilai ini tidak boleh setelah minggu "{{ max }}". - - This value is not a valid slug. - Nilai ini bukan slug yang valid. - This value is not a valid Twig template. Nilai ini bukan templat Twig yang valid. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf index 102cbc9beb7cd..34ef61ed5f8a7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.it.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Questo valore non dovrebbe essere dopo la settimana "{{ max }}". - - This value is not a valid slug. - Questo valore non è uno slug valido. - This value is not a valid Twig template. Questo valore non è un template Twig valido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf index fe928e89604a0..e83aced818553 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". この値は週 "{{ max }}" 以降であってはいけません。 - - This value is not a valid slug. - この値は有効なスラグではありません。 - This value is not a valid Twig template. この値は有効な Twig テンプレートではありません。 diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf index 81bd7de6f717e..d1b5cef57bd0e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Dëse Wäert sollt net no Woch "{{ max }}" sinn. - - This value is not a valid slug. - Dëse Wäert ass kee gültege Slug. - This value is not a valid Twig template. Dëse Wäert ass kee valabelen Twig-Template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf index f9e9f9e220d21..46abd95036044 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lt.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ši reikšmė neturėtų būti po savaitės "{{ max }}". - - This value is not a valid slug. - Ši reikšmė nėra tinkamas slug. - This value is not a valid Twig template. Ši reikšmė nėra tinkamas „Twig“ šablonas. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf index d16d43bf8a7e6..3e2d51a30dec1 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.lv.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Šai vērtībai nevajadzētu būt pēc "{{ max }}" nedēļas. - - This value is not a valid slug. - Šī vērtība nav derīgs URL slug. - This value is not a valid Twig template. Šī vērtība nav derīgs Twig šablons. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf index 6c39949aa1e09..99b1a191b6c0d 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ова вредност не треба да биде по недела "{{ max }}". - - This value is not a valid slug. - Оваа вредност не е валиден slug. - This value is not a valid Twig template. Оваа вредност не е валиден Twig шаблон. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf index b3ee44b43b417..3344675d9ae6a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Энэ утга нь долоо хоног "{{ max }}" -аас хойш байх ёсгүй. - - This value is not a valid slug. - Энэ утга хүчинтэй slug биш байна. - This value is not a valid Twig template. Энэ утга нь Twig-ийн хүчинтэй загвар биш юм. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf index e82ab3b19c8e1..04c955f754509 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.my.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". ဤတန်ဖိုးသည် သီတင်းပတ် "{{ max }}" ပြီးနောက် ဖြစ်သင့်သည်မဟုတ်ပါ။ - - This value is not a valid slug. - ဒီတန်ဖိုးသည်မှန်ကန်သော slug မဟုတ်ပါ။ - This value is not a valid Twig template. ဤတန်ဖိုးသည် မှန်ကန်သော Twig တင်းပလိတ်မဟုတ်ပါ။ diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf index b0281532b4c61..58696f671ca4a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nb.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Denne verdien bør ikke være etter uke "{{ max }}". - - This value is not a valid slug. - Denne verdien er ikke en gyldig slug. - This value is not a valid Twig template. Denne verdien er ikke en gyldig Twig-mal. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf index 10086869427df..0e0de772720c4 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nl.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Deze waarde mag niet na week "{{ max }}" liggen. - - This value is not a valid slug. - Deze waarde is geen geldige slug. - This value is not a valid Twig template. Deze waarde is geen geldige Twig-template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf index 6cb8812b596f1..74d332c06efb2 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.nn.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Denne verdien bør ikkje vere etter veke "{{ max }}". - - This value is not a valid slug. - Denne verdien er ikkje ein gyldig slug. - This value is not a valid Twig template. Denne verdien er ikkje ein gyldig Twig-mal. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf index b0281532b4c61..58696f671ca4a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.no.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Denne verdien bør ikke være etter uke "{{ max }}". - - This value is not a valid slug. - Denne verdien er ikke en gyldig slug. - This value is not a valid Twig template. Denne verdien er ikke en gyldig Twig-mal. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf index 40a3212bc073c..7c243a6b0ca02 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ta wartość nie powinna być po tygodniu "{{ max }}". - - This value is not a valid slug. - Ta wartość nie jest prawidłowym slugiem. - This value is not a valid Twig template. Ta wartość nie jest prawidłowym szablonem Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf index 5732702d7bcde..b6562dbfe712f 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Este valor não deve estar após a semana "{{ max }}". - - This value is not a valid slug. - Este valor não é um slug válido. - This value is not a valid Twig template. Este valor não é um modelo Twig válido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf index a755b2363a314..a6be16580c6bd 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pt_BR.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Este valor não deve estar após a semana "{{ max }}". - - This value is not a valid slug. - Este valor não é um slug válido. - This value is not a valid Twig template. Este valor não é um modelo Twig válido. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf index 56d20634736e7..d6c3b4fb82984 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Această valoare nu trebuie să fie după săptămâna "{{ max }}". - - This value is not a valid slug. - Această valoare nu este un slug valid. - This value is not a valid Twig template. Această valoare nu este un șablon Twig valid. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index dff7ecbbb84c6..e4179779d6c27 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Это значение не должно быть после недели "{{ max }}". - - This value is not a valid slug. - Это значение не является допустимым slug. - This value is not a valid Twig template. Это значение не является допустимым шаблоном Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf index c8d9d912a1750..bba3c291a7fed 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sk.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Táto hodnota by nemala byť po týždni "{{ max }}". - - This value is not a valid slug. - Táto hodnota nie je platný slug. - This value is not a valid Twig template. Táto hodnota nie je platná šablóna Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf index b4cc222ad74d3..28c370e096887 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sl.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ta vrednost ne sme biti po tednu "{{ max }}". - - This value is not a valid slug. - Ta vrednost ni veljaven URL slug. - This value is not a valid Twig template. Ta vrednost ni veljavna predloga Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf index 7ae80b937a37c..ba7178f672ef7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf @@ -475,10 +475,6 @@ This value should not be after week "{{ max }}". Kjo vlerë nuk duhet të jetë pas javës "{{ max }}". - - This value is not a valid slug. - Kjo vlerë nuk është një slug i vlefshëm. - This value is not a valid Twig template. Kjo vlerë nuk është një shabllon Twig i vlefshëm. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf index fa355e47664bc..61040270ac884 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Cyrl.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ова вредност не треба да буде после недеље "{{ max }}". - - This value is not a valid slug. - Ова вредност није валидан слуг. - This value is not a valid Twig template. Ова вредност није важећи Twig шаблон. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf index 61704f6eaaf12..be7ede71376d7 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sr_Latn.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ova vrednost ne treba da bude posle nedelje "{{ max }}". - - This value is not a valid slug. - Ova vrednost nije validan slug. - This value is not a valid Twig template. Ova vrednost nije važeći Twig šablon. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf index c88ffc5823278..692ac7f52d243 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sv.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Det här värdet bör inte vara efter vecka "{{ max }}". - - This value is not a valid slug. - Detta värde är inte en giltig slug. - This value is not a valid Twig template. Det här värdet är inte en giltig Twig-mall. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf index 26371cd6a8bf7..75398a0b84206 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". ค่านี้ไม่ควรจะอยู่หลังสัปดาห์ "{{ max }}" - - This value is not a valid slug. - ค่านี้ไม่ใช่ slug ที่ถูกต้อง - This value is not a valid Twig template. ค่านี้ไม่ใช่เทมเพลต Twig ที่ถูกต้อง diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf index ef1e2ad845caf..729ebc9da9185 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Ang halagang ito ay hindi dapat pagkatapos ng linggo "{{ max }}". - - This value is not a valid slug. - Ang halagang ito ay hindi isang wastong slug. - This value is not a valid Twig template. Ang halagang ito ay hindi isang balidong Twig template. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf index 2cf33ab33c7af..43289337af4cc 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Bu değer “{{ max }}” haftasından sonra olmamalıdır - - This value is not a valid slug. - Bu değer geçerli bir “slug” değildir. - This value is not a valid Twig template. Bu değer geçerli bir Twig şablonu değil. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf index eb4a0db9ec6d0..5f132bc77a6ec 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Це значення не повинно бути після тижня "{{ max }}". - - This value is not a valid slug. - Це значення не є дійсним slug. - This value is not a valid Twig template. Це значення не є дійсним шаблоном Twig. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf index 6a28566ca062e..f13aafb43264b 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ur.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". یہ قدر ہفتہ "{{ max }}" کے بعد نہیں ہونا چاہیے۔ - - This value is not a valid slug. - یہ قدر درست سلاگ نہیں ہے۔ - This value is not a valid Twig template. یہ قدر ایک درست Twig سانچہ نہیں ہے۔ diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf index b54fee24a3cdf..fe0b49f715b12 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.uz.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Bu qiymat "{{ max }}" haftadan keyin bo'lmasligi kerak. - - This value is not a valid slug. - Bu qiymat yaroqli slug emas. - This value is not a valid Twig template. Bu qiymat yaroqli Twig shabloni emas. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf index 8bc1e4c3e078d..9daa4fe8a29d5 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". Giá trị này không nên sau tuần "{{ max }}". - - This value is not a valid slug. - Giá trị này không phải là một slug hợp lệ. - This value is not a valid Twig template. Giá trị này không phải là một mẫu Twig hợp lệ. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf index ff41473e1555e..c570d936ff17c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.zh_CN.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". 该值不应位于 "{{ max }}"周之后。 - - This value is not a valid slug. - 此值不是有效的 slug。 - This value is not a valid Twig template. 此值不是有效的 Twig 模板。 diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf index 7c44889bf8724..d64ea192b7eb2 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf @@ -466,10 +466,6 @@ This value should not be after week "{{ max }}". 這個數值不應晚於第「{{ max }}」週。 - - This value is not a valid slug. - 這個數值不是有效的 slug。 - This value is not a valid Twig template. 此值不是有效的 Twig 模板。 From ea204b92f829f6dc2b1e41da0ec706653a6b0ee2 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Tue, 20 May 2025 03:09:57 +0200 Subject: [PATCH 34/57] [PhpUnitBridge] Clean up mocked features only when group is present --- .../Bridge/PhpUnit/SymfonyExtension.php | 54 ++++++++++++---- .../SymfonyExtensionWithManualRegister.php | 64 +++++++++++++++++++ .../PhpUnit/Tests/symfonyextension.phpt | 13 ++++ 3 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtensionWithManualRegister.php diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php b/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php index 3a429c1493780..c6a5a58e871a0 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php @@ -11,6 +11,8 @@ namespace Symfony\Bridge\PhpUnit; +use PHPUnit\Event\Code\Test; +use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Test\BeforeTestMethodErrored; use PHPUnit\Event\Test\BeforeTestMethodErroredSubscriber; use PHPUnit\Event\Test\Errored; @@ -19,6 +21,7 @@ use PHPUnit\Event\Test\FinishedSubscriber; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\SkippedSubscriber; +use PHPUnit\Metadata\Group; use PHPUnit\Runner\Extension\Extension; use PHPUnit\Runner\Extension\Facade; use PHPUnit\Runner\Extension\ParameterCollection; @@ -47,22 +50,22 @@ public function bootstrap(Configuration $configuration, Facade $facade, Paramete $facade->registerSubscriber(new class implements ErroredSubscriber { public function notify(Errored $event): void { - SymfonyExtension::disableClockMock(); - SymfonyExtension::disableDnsMock(); + SymfonyExtension::disableClockMock($event->test()); + SymfonyExtension::disableDnsMock($event->test()); } }); $facade->registerSubscriber(new class implements FinishedSubscriber { public function notify(Finished $event): void { - SymfonyExtension::disableClockMock(); - SymfonyExtension::disableDnsMock(); + SymfonyExtension::disableClockMock($event->test()); + SymfonyExtension::disableDnsMock($event->test()); } }); $facade->registerSubscriber(new class implements SkippedSubscriber { public function notify(Skipped $event): void { - SymfonyExtension::disableClockMock(); - SymfonyExtension::disableDnsMock(); + SymfonyExtension::disableClockMock($event->test()); + SymfonyExtension::disableDnsMock($event->test()); } }); @@ -70,8 +73,13 @@ public function notify(Skipped $event): void $facade->registerSubscriber(new class implements BeforeTestMethodErroredSubscriber { public function notify(BeforeTestMethodErrored $event): void { - SymfonyExtension::disableClockMock(); - SymfonyExtension::disableDnsMock(); + if (method_exists($event, 'test')) { + SymfonyExtension::disableClockMock($event->test()); + SymfonyExtension::disableDnsMock($event->test()); + } else { + ClockMock::withClockMock(false); + DnsMock::withMockedHosts([]); + } } }); } @@ -88,16 +96,38 @@ public function notify(BeforeTestMethodErrored $event): void /** * @internal */ - public static function disableClockMock(): void + public static function disableClockMock(Test $test): void { - ClockMock::withClockMock(false); + if (self::hasGroup($test, 'time-sensitive')) { + ClockMock::withClockMock(false); + } } /** * @internal */ - public static function disableDnsMock(): void + public static function disableDnsMock(Test $test): void { - DnsMock::withMockedHosts([]); + if (self::hasGroup($test, 'dns-sensitive')) { + DnsMock::withMockedHosts([]); + } + } + + /** + * @internal + */ + public static function hasGroup(Test $test, string $groupName): bool + { + if (!$test instanceof TestMethod) { + return false; + } + + foreach ($test->metadata() as $metadata) { + if ($metadata instanceof Group && $groupName === $metadata->groupName()) { + return true; + } + } + + return false; } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtensionWithManualRegister.php b/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtensionWithManualRegister.php new file mode 100644 index 0000000000000..c02d6f1cf64ce --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/SymfonyExtensionWithManualRegister.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ClockMock; +use Symfony\Bridge\PhpUnit\DnsMock; + +class SymfonyExtensionWithManualRegister extends TestCase +{ + public static function setUpBeforeClass(): void + { + ClockMock::register(self::class); + ClockMock::withClockMock(strtotime('2024-05-20 15:30:00')); + + DnsMock::register(self::class); + DnsMock::withMockedHosts([ + 'example.com' => [ + ['type' => 'A', 'ip' => '1.2.3.4'], + ], + ]); + } + + public static function tearDownAfterClass(): void + { + ClockMock::withClockMock(false); + DnsMock::withMockedHosts([]); + } + + public function testDate() + { + self::assertSame('2024-05-20 15:30:00', date('Y-m-d H:i:s')); + } + + public function testGetHostByName() + { + self::assertSame('1.2.3.4', gethostbyname('example.com')); + } + + public function testTime() + { + self::assertSame(1716219000, time()); + } + + public function testDnsGetRecord() + { + self::assertSame([[ + 'host' => 'example.com', + 'class' => 'IN', + 'ttl' => 1, + 'type' => 'A', + 'ip' => '1.2.3.4', + ]], dns_get_record('example.com')); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/symfonyextension.phpt b/src/Symfony/Bridge/PhpUnit/Tests/symfonyextension.phpt index 2c808c2f5930e..02b0a510e6301 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/symfonyextension.phpt +++ b/src/Symfony/Bridge/PhpUnit/Tests/symfonyextension.phpt @@ -5,6 +5,8 @@ if (!getenv('SYMFONY_PHPUNIT_VERSION') || version_compare(getenv('SYMFONY_PHPUNI --FILE-- Date: Tue, 20 May 2025 10:28:02 +0200 Subject: [PATCH 35/57] Update Turkish translation for Twig template validation message --- .../Validator/Resources/translations/validators.tr.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf index 43289337af4cc..42c4bbd91ebab 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf @@ -468,7 +468,7 @@ This value is not a valid Twig template. - Bu değer geçerli bir Twig şablonu değil. + Bu değer geçerli bir Twig şablonu olarak kabul edilmiyor. From 03a02acdcf85ab35a8e6279125fb68e2de76b2e5 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 20 May 2025 11:40:57 +0200 Subject: [PATCH 36/57] set path to the PHPUnit autoload file --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index 0472e8c1d81b3..590a886350c79 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -386,6 +386,10 @@ class_exists(\SymfonyExcludeListSimplePhpunit::class, false) && PHPUnit\Util\Bla $cmd .= '%2$s'; } +if (version_compare($PHPUNIT_VERSION, '11.0', '>=')) { + $GLOBALS['_composer_autoload_path'] = "$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/vendor/autoload.php"; +} + if ($components) { $skippedTests = $_SERVER['SYMFONY_PHPUNIT_SKIPPED_TESTS'] ?? false; $runningProcs = []; From 307d743084462b29a1bd9816f5ad3befd22cdfcb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 20 May 2025 10:48:43 +0200 Subject: [PATCH 37/57] [FrameworkBundle] Fix activation strategy of traceable decorators --- src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php | 9 +++++++++ .../FrameworkBundle/Resources/config/profiling.php | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 7c5ba6e39e121..300fe22fb37a9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddDebugLogProcessorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AssetsContextPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; @@ -202,6 +203,14 @@ public function build(ContainerBuilder $container): void } } + /** + * @internal + */ + public static function considerProfilerEnabled(): bool + { + return !($GLOBALS['app'] ?? null) instanceof Application || empty($_GET) && \in_array('--profile', $_SERVER['argv'] ?? [], true); + } + private function addCompilerPassIfExists(ContainerBuilder $container, string $class, string $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): void { $container->addResource(new ClassExistenceResource($class)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php index 68fb295bb8768..a81c53a633461 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Symfony\Bundle\FrameworkBundle\EventListener\ConsoleProfilerListener; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Component\HttpKernel\Debug\VirtualRequestStack; use Symfony\Component\HttpKernel\EventListener\ProfilerListener; use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage; @@ -61,7 +62,7 @@ ->set('profiler.state_checker', ProfilerStateChecker::class) ->args([ service_locator(['profiler' => service('profiler')->ignoreOnUninitialized()]), - param('kernel.runtime_mode.web'), + inline_service('bool')->factory([FrameworkBundle::class, 'considerProfilerEnabled']), ]) ->set('profiler.is_disabled_state_checker', 'Closure') From 5b2634ff8c7da371c04338953172847fc81cfb2c Mon Sep 17 00:00:00 2001 From: maciekpaprocki Date: Tue, 20 May 2025 11:29:20 +0100 Subject: [PATCH 38/57] added earlier skip to allow if=false when using source mapping --- src/Symfony/Component/ObjectMapper/ObjectMapper.php | 6 +++--- .../Tests/Fixtures/HydrateObject/SourceOnly.php | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/ObjectMapper/ObjectMapper.php b/src/Symfony/Component/ObjectMapper/ObjectMapper.php index 7624a05f7bfe0..d78bc3ce8d216 100644 --- a/src/Symfony/Component/ObjectMapper/ObjectMapper.php +++ b/src/Symfony/Component/ObjectMapper/ObjectMapper.php @@ -122,12 +122,12 @@ public function map(object $source, object|string|null $target = null): object $sourcePropertyName = $mapping->source; } - $value = $this->getRawValue($source, $sourcePropertyName); - if (($if = $mapping->if) && ($fn = $this->getCallable($if, $this->conditionCallableLocator)) && !$this->call($fn, $value, $source, $mappedTarget)) { + if (false === $if = $mapping->if) { continue; } - if (false === $if) { + $value = $this->getRawValue($source, $sourcePropertyName); + if ($if && ($fn = $this->getCallable($if, $this->conditionCallableLocator)) && !$this->call($fn, $value, $source, $mappedTarget)) { continue; } diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/HydrateObject/SourceOnly.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/HydrateObject/SourceOnly.php index 9e3127b80d965..c062427c6e8d0 100644 --- a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/HydrateObject/SourceOnly.php +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/HydrateObject/SourceOnly.php @@ -15,7 +15,9 @@ class SourceOnly { - public function __construct(#[Map(source: 'name')] public string $mappedName) - { + public function __construct( + #[Map(source: 'name')] public string $mappedName, + #[Map(if: false)] public ?string $mappedDescription = null + ) { } } From 82d7ecdec3f8ea2f71be19026ba26707fc50e48a Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 20 May 2025 13:53:54 +0200 Subject: [PATCH 39/57] [FrameworkBundle] object mapper service definition without form --- .../DependencyInjection/FrameworkExtension.php | 16 ++++++++-------- .../FrameworkExtensionTestCase.php | 8 ++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 385a4caf38ded..912282f495dac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -642,6 +642,14 @@ public function load(array $configs, ContainerBuilder $container): void $loader->load('mime_type.php'); } + if (ContainerBuilder::willBeAvailable('symfony/object-mapper', ObjectMapperInterface::class, ['symfony/framework-bundle'])) { + $loader->load('object_mapper.php'); + $container->registerForAutoconfiguration(TransformCallableInterface::class) + ->addTag('object_mapper.transform_callable'); + $container->registerForAutoconfiguration(ConditionCallableInterface::class) + ->addTag('object_mapper.condition_callable'); + } + $container->registerForAutoconfiguration(PackageInterface::class) ->addTag('assets.package'); $container->registerForAutoconfiguration(AssetCompilerInterface::class) @@ -880,14 +888,6 @@ private function registerFormConfiguration(array $config, ContainerBuilder $cont if (!ContainerBuilder::willBeAvailable('symfony/translation', Translator::class, ['symfony/framework-bundle', 'symfony/form'])) { $container->removeDefinition('form.type_extension.upload.validator'); } - - if (ContainerBuilder::willBeAvailable('symfony/object-mapper', ObjectMapperInterface::class, ['symfony/framework-bundle'])) { - $loader->load('object_mapper.php'); - $container->registerForAutoconfiguration(TransformCallableInterface::class) - ->addTag('object_mapper.transform_callable'); - $container->registerForAutoconfiguration(ConditionCallableInterface::class) - ->addTag('object_mapper.condition_callable'); - } } private function registerHttpCacheConfiguration(array $config, ContainerBuilder $container, bool $httpMethodOverride): void diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index 990e1e8c252d4..8b452d4c8baf4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -2600,6 +2600,14 @@ public function testJsonStreamerEnabled() $this->assertTrue($container->has('json_streamer.stream_writer')); } + public function testObjectMapperEnabled() + { + $container = $this->createContainerFromClosure(function (ContainerBuilder $container) { + $container->loadFromExtension('framework', []); + }); + $this->assertTrue($container->has('object_mapper')); + } + protected function createContainer(array $data = []) { return new ContainerBuilder(new EnvPlaceholderParameterBag(array_merge([ From 6468ac18ef5d38069a64f39d207cc66e8e328d5e Mon Sep 17 00:00:00 2001 From: es Date: Tue, 20 May 2025 17:15:13 +0300 Subject: [PATCH 40/57] review translation messages(be) --- .../Resources/translations/security.be.xlf | 2 +- .../Resources/translations/validators.be.xlf | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf index 194392935fcc1..6478e2a15caf7 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.be.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Занадта шмат няўдалых спробаў уваходу, калі ласка, паспрабуйце зноў праз %minutes% хвіліну.|Занадта шмат няўдалых спробаў уваходу, калі ласка, паспрабуйце зноў праз %minutes% хвіліны.|Занадта шмат няўдалых спробаў уваходу, калі ласка, паспрабуйце зноў праз %minutes% хвілін. + Занадта вялікая колькасць няўдалых спробаў уваходу. Калі ласка, паспрабуйце зноў праз %minutes% хвіліну.|Занадта вялікая колькасць няўдалых спробаў уваходу. Калі ласка, паспрабуйце зноў праз %minutes% хвіліны.|Занадта вялікая колькасць няўдалых спробаў уваходу. Калі ласка, паспрабуйце зноў праз %minutes% хвілін. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf index 7308820465dfa..7b24df5e5c189 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.be.xlf @@ -136,7 +136,7 @@ This value is not a valid IP address. - Гэта значэнне не з'яўляецца сапраўдным IP-адрасам. + Гэта значэнне не з'яўляецца сапраўдным IP-адрасам. This value is not a valid language. @@ -224,7 +224,7 @@ This value is not a valid International Bank Account Number (IBAN). - Гэта значэнне не з'яўляецца сапраўдным міжнародным нумарам банкаўскага рахунку (IBAN). + Гэта значэнне не з'яўляецца сапраўдным міжнародным нумарам банкаўскага рахунку (IBAN). This value is not a valid ISBN-10. @@ -312,7 +312,7 @@ This value is not a valid Business Identifier Code (BIC). - Гэта значэнне не з'яўляецца сапраўдным кодам ідэнтыфікацыі бізнесу (BIC). + Гэта значэнне не з'яўляецца сапраўдным кодам ідэнтыфікацыі банка (BIC). Error @@ -320,7 +320,7 @@ This value is not a valid UUID. - Гэта значэнне не з'яўляецца сапраўдным UUID. + Гэта значэнне не з'яўляецца сапраўдным UUID. This value should be a multiple of {{ compared_value }}. @@ -428,47 +428,47 @@ The extension of the file is invalid ({{ extension }}). Allowed extensions are {{ extensions }}. - Пашырэнне файла няслушнае ({{ extension }}). Дазволеныя пашырэнні: {{ extensions }}. + Пашырэнне файла недапушчальнае ({{ extension }}). Дазволеныя пашырэнні: {{ extensions }}. The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}. - Выяўленая кадыроўка знакаў няслушная ({{ detected }}). Дазволеныя кадыроўкі: {{ encodings }}. + Выяўленая кадзіроўка недапушчальная ({{ detected }}). Дазволеныя кадзіроўкі: {{ encodings }}. This value is not a valid MAC address. - Гэта значэнне не з'яўляецца сапраўдным MAC-адрасам. + Гэта значэнне не з'яўляецца сапраўдным MAC-адрасам. This URL is missing a top-level domain. - Гэтаму URL бракуе дамен верхняга ўзроўню. + Гэтаму URL бракуе дамен верхняга ўзроўню. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Гэта значэнне занадта кароткае. Яно павінна ўтрымліваць хаця б адно слова.|Гэта значэнне занадта кароткае. Яно павінна ўтрымліваць хаця б {{ min }} словы. + Гэта значэнне занадта кароткае. Яно павінна ўтрымліваць хаця б адно слова.|Гэта значэнне занадта кароткае. Яно павінна ўтрымліваць хаця б {{ min }} слоў. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Гэта значэнне занадта доўгае. Яно павінна ўтрымліваць адно слова.|Гэта значэнне занадта доўгае. Яно павінна ўтрымліваць {{ max }} словы або менш. + Гэта значэнне занадта доўгае. Яно павінна ўтрымліваць адно слова.|Гэта значэнне занадта доўгае. Яно павінна ўтрымліваць {{ max }} слоў або менш. This value does not represent a valid week in the ISO 8601 format. - Гэта значэнне не адпавядае правільнаму тыдні ў фармаце ISO 8601. + Гэта значэнне не адпавядае сапраўднаму тыдню ў фармаце ISO 8601. This value is not a valid week. - Гэта значэнне не з'яўляецца сапраўдным тыднем. + Гэта значэнне не з'яўляецца сапраўдным тыднем. This value should not be before week "{{ min }}". - Гэта значэнне не павінна быць раней за тыдзень "{{ min }}". + Гэта значэнне не павінна быць раней за тыдзень "{{ min }}". This value should not be after week "{{ max }}". - Гэта значэнне не павінна быць пасля тыдня "{{ max }}". + Гэта значэнне не павінна быць пасля тыдня "{{ max }}". This value is not a valid Twig template. - Гэта значэнне не з'яўляецца сапраўдным шаблонам Twig. + Гэта значэнне не з'яўляецца сапраўдным шаблонам Twig. From 6efc2045a16a1668aadcc1e179c7ec58bc1b2632 Mon Sep 17 00:00:00 2001 From: Link1515 Date: Tue, 20 May 2025 18:08:09 +0800 Subject: [PATCH 41/57] Review translations for Chinese (zh_TW) --- .../Validator/Resources/translations/validators.zh_TW.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf index d64ea192b7eb2..a60283b280898 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.zh_TW.xlf @@ -468,7 +468,7 @@ This value is not a valid Twig template. - 此值不是有效的 Twig 模板。 + 這個數值不是有效的 Twig 模板。 From 4cdbbe51b79415df76018acce2b8e114ba5aaff5 Mon Sep 17 00:00:00 2001 From: Ignacio Alveal Date: Tue, 20 May 2025 12:54:44 -0400 Subject: [PATCH 42/57] fix: Add argument as integer Co-authored-by: Guillermo Fuentes --- .../Component/Messenger/Bridge/Amqp/Transport/Connection.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php index 0ae1bff21d7c8..061bbcb47d124 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php @@ -31,6 +31,7 @@ class Connection 'x-max-length-bytes', 'x-max-priority', 'x-message-ttl', + 'x-delivery-limit', ]; /** From 5ec5f407e575cebd18edd96f5fe3d089bdb55ec2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 21 May 2025 09:40:19 +0200 Subject: [PATCH 43/57] fix merge --- src/Symfony/Component/Validator/Constraints/Image.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/Image.php b/src/Symfony/Component/Validator/Constraints/Image.php index 0dd09bf1f165f..5812b9a4989a4 100644 --- a/src/Symfony/Component/Validator/Constraints/Image.php +++ b/src/Symfony/Component/Validator/Constraints/Image.php @@ -58,7 +58,7 @@ class Image extends File self::CORRUPTED_IMAGE_ERROR => 'CORRUPTED_IMAGE_ERROR', ]; - public array|string $mimeTypes = 'image/*'; + public array|string $mimeTypes = []; public ?int $minWidth = null; public ?int $maxWidth = null; public ?int $maxHeight = null; @@ -220,7 +220,7 @@ public function __construct( $this->allowPortraitMessage = $allowPortraitMessage ?? $this->allowPortraitMessage; $this->corruptedMessage = $corruptedMessage ?? $this->corruptedMessage; - if (null === $this->mimeTypes && [] === $this->extensions) { + if ([] === $this->mimeTypes && [] === $this->extensions) { $this->mimeTypes = 'image/*'; } From 7e09dc03208d75b8879ee031568e9731073fbbb8 Mon Sep 17 00:00:00 2001 From: PatrickRedStar Date: Wed, 21 May 2025 14:12:29 +0300 Subject: [PATCH 44/57] validate translate src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf:471 --- .../Validator/Resources/translations/validators.ru.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index e4179779d6c27..727ae0aefdf86 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -468,7 +468,7 @@ This value is not a valid Twig template. - Это значение не является допустимым шаблоном Twig. + Это значение не является корректным шаблоном Twig. From 7d63c76de82c906e398c104e9848063b5fa5e10f Mon Sep 17 00:00:00 2001 From: HypeMC Date: Wed, 21 May 2025 14:18:26 +0200 Subject: [PATCH 45/57] [PropertyInfo] Improve deprecation message --- .../FrameworkBundle/DependencyInjection/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 0e9b20b0ca015..f4e137f04b980 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -1290,7 +1290,7 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode, callable ->then(function ($v) { $v['property_info']['with_constructor_extractor'] = false; - trigger_deprecation('symfony/framework-bundle', '7.3', 'Not setting the "with_constructor_extractor" option explicitly is deprecated because its default value will change in version 8.0.'); + trigger_deprecation('symfony/framework-bundle', '7.3', 'Not setting the "property_info.with_constructor_extractor" option explicitly is deprecated because its default value will change in version 8.0.'); return $v; }) From c6ceb0cc94b07fcac091cc7f1c8d6068bdd029b9 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 22 May 2025 13:56:34 +0200 Subject: [PATCH 46/57] meaningfully error in DeduplicateStamp if the Lock component is missing --- src/Symfony/Component/Messenger/Stamp/DeduplicateStamp.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Component/Messenger/Stamp/DeduplicateStamp.php b/src/Symfony/Component/Messenger/Stamp/DeduplicateStamp.php index 4e08d5369f261..1b9ff480b4f49 100644 --- a/src/Symfony/Component/Messenger/Stamp/DeduplicateStamp.php +++ b/src/Symfony/Component/Messenger/Stamp/DeduplicateStamp.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger\Stamp; use Symfony\Component\Lock\Key; +use Symfony\Component\Messenger\Exception\LogicException; final class DeduplicateStamp implements StampInterface { @@ -22,6 +23,10 @@ public function __construct( private ?float $ttl = 300.0, private bool $onlyDeduplicateInQueue = false, ) { + if (!class_exists(Key::class)) { + throw new LogicException(\sprintf('You cannot use the "%s" as the Lock component is not installed. Try running "composer require symfony/lock".', self::class)); + } + $this->key = new Key($key); } From 62da782fd3941e75bf150a52eebb6935623ad814 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Wed, 21 May 2025 14:00:46 +0200 Subject: [PATCH 47/57] [PhpUnitBridge] Fix cleaning up mocked features with attributes --- .github/workflows/phpunit-bridge.yml | 2 +- .../Bridge/PhpUnit/SymfonyExtension.php | 54 ++++++++++++------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml index 56360c4c3d80a..5de320ee91c0e 100644 --- a/.github/workflows/phpunit-bridge.yml +++ b/.github/workflows/phpunit-bridge.yml @@ -35,4 +35,4 @@ jobs: php-version: "7.2" - name: Lint - run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e /Attribute/ -e /Extension/ -e /Metadata/ -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait | parallel -j 4 php -l {} + run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e /Attribute/ -e /Extension/ -e /Metadata/ -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait -e SymfonyExtension | parallel -j 4 php -l {} diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php b/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php index f290a2c228865..05ff99aa8aedc 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyExtension.php @@ -26,6 +26,8 @@ use PHPUnit\Runner\Extension\Facade; use PHPUnit\Runner\Extension\ParameterCollection; use PHPUnit\TextUI\Configuration\Configuration; +use Symfony\Bridge\PhpUnit\Attribute\DnsSensitive; +use Symfony\Bridge\PhpUnit\Attribute\TimeSensitive; use Symfony\Bridge\PhpUnit\Extension\EnableClockMockSubscriber; use Symfony\Bridge\PhpUnit\Extension\RegisterClockMockSubscriber; use Symfony\Bridge\PhpUnit\Extension\RegisterDnsMockSubscriber; @@ -50,35 +52,51 @@ public function bootstrap(Configuration $configuration, Facade $facade, Paramete $facade->registerSubscriber(new RegisterClockMockSubscriber($reader)); $facade->registerSubscriber(new EnableClockMockSubscriber($reader)); - $facade->registerSubscriber(new class implements ErroredSubscriber { + $facade->registerSubscriber(new class($reader) implements ErroredSubscriber { + public function __construct(private AttributeReader $reader) + { + } + public function notify(Errored $event): void { - SymfonyExtension::disableClockMock($event->test()); - SymfonyExtension::disableDnsMock($event->test()); + SymfonyExtension::disableClockMock($event->test(), $this->reader); + SymfonyExtension::disableDnsMock($event->test(), $this->reader); } }); - $facade->registerSubscriber(new class implements FinishedSubscriber { + $facade->registerSubscriber(new class($reader) implements FinishedSubscriber { + public function __construct(private AttributeReader $reader) + { + } + public function notify(Finished $event): void { - SymfonyExtension::disableClockMock($event->test()); - SymfonyExtension::disableDnsMock($event->test()); + SymfonyExtension::disableClockMock($event->test(), $this->reader); + SymfonyExtension::disableDnsMock($event->test(), $this->reader); } }); - $facade->registerSubscriber(new class implements SkippedSubscriber { + $facade->registerSubscriber(new class($reader) implements SkippedSubscriber { + public function __construct(private AttributeReader $reader) + { + } + public function notify(Skipped $event): void { - SymfonyExtension::disableClockMock($event->test()); - SymfonyExtension::disableDnsMock($event->test()); + SymfonyExtension::disableClockMock($event->test(), $this->reader); + SymfonyExtension::disableDnsMock($event->test(), $this->reader); } }); if (interface_exists(BeforeTestMethodErroredSubscriber::class)) { - $facade->registerSubscriber(new class implements BeforeTestMethodErroredSubscriber { + $facade->registerSubscriber(new class($reader) implements BeforeTestMethodErroredSubscriber { + public function __construct(private AttributeReader $reader) + { + } + public function notify(BeforeTestMethodErrored $event): void { if (method_exists($event, 'test')) { - SymfonyExtension::disableClockMock($event->test()); - SymfonyExtension::disableDnsMock($event->test()); + SymfonyExtension::disableClockMock($event->test(), $this->reader); + SymfonyExtension::disableDnsMock($event->test(), $this->reader); } else { ClockMock::withClockMock(false); DnsMock::withMockedHosts([]); @@ -99,9 +117,9 @@ public function notify(BeforeTestMethodErrored $event): void /** * @internal */ - public static function disableClockMock(Test $test): void + public static function disableClockMock(Test $test, AttributeReader $reader): void { - if (self::hasGroup($test, 'time-sensitive')) { + if (self::hasGroup($test, 'time-sensitive', $reader, TimeSensitive::class)) { ClockMock::withClockMock(false); } } @@ -109,9 +127,9 @@ public static function disableClockMock(Test $test): void /** * @internal */ - public static function disableDnsMock(Test $test): void + public static function disableDnsMock(Test $test, AttributeReader $reader): void { - if (self::hasGroup($test, 'dns-sensitive')) { + if (self::hasGroup($test, 'dns-sensitive', $reader, DnsSensitive::class)) { DnsMock::withMockedHosts([]); } } @@ -119,7 +137,7 @@ public static function disableDnsMock(Test $test): void /** * @internal */ - public static function hasGroup(Test $test, string $groupName): bool + public static function hasGroup(Test $test, string $groupName, AttributeReader $reader, string $attribute): bool { if (!$test instanceof TestMethod) { return false; @@ -131,6 +149,6 @@ public static function hasGroup(Test $test, string $groupName): bool } } - return false; + return [] !== $reader->forClassAndMethod($test->className(), $test->methodName(), $attribute); } } From 0d6cda354b3f4358cdadc4d81800ee94a5241760 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 23 May 2025 10:51:09 +0200 Subject: [PATCH 48/57] also reject \DateTime subclasses --- .../Read/DateTimeTypePropertyMetadataLoader.php | 2 +- .../DateTimeTypePropertyMetadataLoaderTest.php | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/JsonStreamer/Mapping/Read/DateTimeTypePropertyMetadataLoader.php b/src/Symfony/Component/JsonStreamer/Mapping/Read/DateTimeTypePropertyMetadataLoader.php index 11ce2b4f93962..26bc022cae2e3 100644 --- a/src/Symfony/Component/JsonStreamer/Mapping/Read/DateTimeTypePropertyMetadataLoader.php +++ b/src/Symfony/Component/JsonStreamer/Mapping/Read/DateTimeTypePropertyMetadataLoader.php @@ -38,7 +38,7 @@ public function load(string $className, array $options = [], array $context = [] $type = $metadata->getType(); if ($type instanceof ObjectType && is_a($type->getClassName(), \DateTimeInterface::class, true)) { - if (\DateTime::class === $type->getClassName()) { + if (is_a($type->getClassName(), \DateTime::class, true)) { throw new InvalidArgumentException('The "DateTime" class is not supported. Use "DateTimeImmutable" instead.'); } diff --git a/src/Symfony/Component/JsonStreamer/Tests/Mapping/Read/DateTimeTypePropertyMetadataLoaderTest.php b/src/Symfony/Component/JsonStreamer/Tests/Mapping/Read/DateTimeTypePropertyMetadataLoaderTest.php index c71189815be29..779499adf21c2 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Mapping/Read/DateTimeTypePropertyMetadataLoaderTest.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Mapping/Read/DateTimeTypePropertyMetadataLoaderTest.php @@ -47,6 +47,18 @@ public function testThrowWhenDateTimeType() $loader->load(self::class); } + public function testThrowWhenDateTimeSubclassType() + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The "DateTime" class is not supported. Use "DateTimeImmutable" instead.'); + + $loader = new DateTimeTypePropertyMetadataLoader(self::propertyMetadataLoader([ + 'mutable' => new PropertyMetadata('mutable', Type::object(DateTimeChild::class)), + ])); + + $loader->load(self::class); + } + /** * @param array $propertiesMetadata */ @@ -64,3 +76,7 @@ public function load(string $className, array $options = [], array $context = [] }; } } + +class DateTimeChild extends \DateTime +{ +} From 734e60aa338244975d15fbce2cf0214253f5e2ea Mon Sep 17 00:00:00 2001 From: Fabien Salathe Date: Sat, 24 May 2025 01:18:01 +0900 Subject: [PATCH 49/57] [Notifier] Fix Clicksend transport --- .../Notifier/Bridge/ClickSend/ClickSendTransport.php | 2 +- .../Bridge/ClickSend/Tests/ClickSendTransportTest.php | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Notifier/Bridge/ClickSend/ClickSendTransport.php b/src/Symfony/Component/Notifier/Bridge/ClickSend/ClickSendTransport.php index 0e5bd147d3f61..f60e4e23ee3f9 100644 --- a/src/Symfony/Component/Notifier/Bridge/ClickSend/ClickSendTransport.php +++ b/src/Symfony/Component/Notifier/Bridge/ClickSend/ClickSendTransport.php @@ -87,7 +87,7 @@ protected function doSend(MessageInterface $message): SentMessage $response = $this->client->request('POST', $endpoint, [ 'auth_basic' => [$this->apiUsername, $this->apiKey], - 'json' => array_filter($options), + 'json' => ['messages' => [array_filter($options)]], ]); try { diff --git a/src/Symfony/Component/Notifier/Bridge/ClickSend/Tests/ClickSendTransportTest.php b/src/Symfony/Component/Notifier/Bridge/ClickSend/Tests/ClickSendTransportTest.php index 166bb10d8a8dc..ba7923a7fa231 100644 --- a/src/Symfony/Component/Notifier/Bridge/ClickSend/Tests/ClickSendTransportTest.php +++ b/src/Symfony/Component/Notifier/Bridge/ClickSend/Tests/ClickSendTransportTest.php @@ -63,10 +63,14 @@ public function testNoInvalidArgumentExceptionIsThrownIfFromIsValid(string $from $response = $this->createMock(ResponseInterface::class); $response->expects(self::exactly(2))->method('getStatusCode')->willReturn(200); $response->expects(self::once())->method('getContent')->willReturn(''); - $client = new MockHttpClient(function (string $method, string $url) use ($response): ResponseInterface { + $client = new MockHttpClient(function (string $method, string $url, array $options) use ($response): ResponseInterface { self::assertSame('POST', $method); self::assertSame('https://rest.clicksend.com/v3/sms/send', $url); + $body = json_decode($options['body'], true); + self::assertIsArray($body); + self::assertArrayHasKey('messages', $body); + return $response; }); $transport = $this->createTransport($client, $from); From c9d7c63cbe5ef82a34a5ced5720f97a8cc43feb1 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Sat, 17 May 2025 19:37:35 -0400 Subject: [PATCH 50/57] [Console] Improve `#[Argument]`/`#[Option]` exception messages --- .../Component/Console/Attribute/Argument.php | 11 ++++++++-- .../Component/Console/Attribute/Option.php | 21 ++++++++++++------ .../Tests/Command/InvokableCommandTest.php | 22 +++++-------------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/Symfony/Component/Console/Attribute/Argument.php b/src/Symfony/Component/Console/Attribute/Argument.php index 22bfbf48b762d..e6a94d2f10e4c 100644 --- a/src/Symfony/Component/Console/Attribute/Argument.php +++ b/src/Symfony/Component/Console/Attribute/Argument.php @@ -26,6 +26,7 @@ class Argument private string|bool|int|float|array|null $default = null; private array|\Closure $suggestedValues; private ?int $mode = null; + private string $function = ''; /** * Represents a console command definition. @@ -52,17 +53,23 @@ public static function tryFrom(\ReflectionParameter $parameter): ?self return null; } + if (($function = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod) { + $self->function = $function->class.'::'.$function->name; + } else { + $self->function = $function->name; + } + $type = $parameter->getType(); $name = $parameter->getName(); if (!$type instanceof \ReflectionNamedType) { - throw new LogicException(\sprintf('The parameter "$%s" must have a named type. Untyped, Union or Intersection types are not supported for command arguments.', $name)); + throw new LogicException(\sprintf('The parameter "$%s" of "%s()" must have a named type. Untyped, Union or Intersection types are not supported for command arguments.', $name, $self->function)); } $parameterTypeName = $type->getName(); if (!\in_array($parameterTypeName, self::ALLOWED_TYPES, true)) { - throw new LogicException(\sprintf('The type "%s" of parameter "$%s" is not supported as a command argument. Only "%s" types are allowed.', $parameterTypeName, $name, implode('", "', self::ALLOWED_TYPES))); + throw new LogicException(\sprintf('The type "%s" on parameter "$%s" of "%s()" is not supported as a command argument. Only "%s" types are allowed.', $parameterTypeName, $name, $self->function, implode('", "', self::ALLOWED_TYPES))); } if (!$self->name) { diff --git a/src/Symfony/Component/Console/Attribute/Option.php b/src/Symfony/Component/Console/Attribute/Option.php index 19c82317033c4..2f0256b177658 100644 --- a/src/Symfony/Component/Console/Attribute/Option.php +++ b/src/Symfony/Component/Console/Attribute/Option.php @@ -29,6 +29,7 @@ class Option private ?int $mode = null; private string $typeName = ''; private bool $allowNull = false; + private string $function = ''; /** * Represents a console command --option definition. @@ -57,11 +58,17 @@ public static function tryFrom(\ReflectionParameter $parameter): ?self return null; } + if (($function = $parameter->getDeclaringFunction()) instanceof \ReflectionMethod) { + $self->function = $function->class.'::'.$function->name; + } else { + $self->function = $function->name; + } + $name = $parameter->getName(); $type = $parameter->getType(); if (!$parameter->isDefaultValueAvailable()) { - throw new LogicException(\sprintf('The option parameter "$%s" must declare a default value.', $name)); + throw new LogicException(\sprintf('The option parameter "$%s" of "%s()" must declare a default value.', $name, $self->function)); } if (!$self->name) { @@ -76,21 +83,21 @@ public static function tryFrom(\ReflectionParameter $parameter): ?self } if (!$type instanceof \ReflectionNamedType) { - throw new LogicException(\sprintf('The parameter "$%s" must have a named type. Untyped or Intersection types are not supported for command options.', $name)); + throw new LogicException(\sprintf('The parameter "$%s" of "%s()" must have a named type. Untyped or Intersection types are not supported for command options.', $name, $self->function)); } $self->typeName = $type->getName(); if (!\in_array($self->typeName, self::ALLOWED_TYPES, true)) { - throw new LogicException(\sprintf('The type "%s" of parameter "$%s" is not supported as a command option. Only "%s" types are allowed.', $self->typeName, $name, implode('", "', self::ALLOWED_TYPES))); + throw new LogicException(\sprintf('The type "%s" on parameter "$%s" of "%s()" is not supported as a command option. Only "%s" types are allowed.', $self->typeName, $name, $self->function, implode('", "', self::ALLOWED_TYPES))); } if ('bool' === $self->typeName && $self->allowNull && \in_array($self->default, [true, false], true)) { - throw new LogicException(\sprintf('The option parameter "$%s" must not be nullable when it has a default boolean value.', $name)); + throw new LogicException(\sprintf('The option parameter "$%s" of "%s()" must not be nullable when it has a default boolean value.', $name, $self->function)); } if ($self->allowNull && null !== $self->default) { - throw new LogicException(\sprintf('The option parameter "$%s" must either be not-nullable or have a default of null.', $name)); + throw new LogicException(\sprintf('The option parameter "$%s" of "%s()" must either be not-nullable or have a default of null.', $name, $self->function)); } if ('bool' === $self->typeName) { @@ -160,11 +167,11 @@ private function handleUnion(\ReflectionUnionType $type): self $this->typeName = implode('|', array_filter($types)); if (!\in_array($this->typeName, self::ALLOWED_UNION_TYPES, true)) { - throw new LogicException(\sprintf('The union type for parameter "$%s" is not supported as a command option. Only "%s" types are allowed.', $this->name, implode('", "', self::ALLOWED_UNION_TYPES))); + throw new LogicException(\sprintf('The union type for parameter "$%s" of "%s()" is not supported as a command option. Only "%s" types are allowed.', $this->name, $this->function, implode('", "', self::ALLOWED_UNION_TYPES))); } if (false !== $this->default) { - throw new LogicException(\sprintf('The option parameter "$%s" must have a default value of false.', $this->name)); + throw new LogicException(\sprintf('The option parameter "$%s" of "%s()" must have a default value of false.', $this->name, $this->function)); } $this->mode = InputOption::VALUE_OPTIONAL; diff --git a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php index 917e2f88f1655..5ab7951e7f575 100644 --- a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php @@ -138,7 +138,6 @@ public function testInvalidArgumentType() $command->setCode(function (#[Argument] object $any) {}); $this->expectException(LogicException::class); - $this->expectExceptionMessage('The type "object" of parameter "$any" is not supported as a command argument. Only "string", "bool", "int", "float", "array" types are allowed.'); $command->getDefinition(); } @@ -149,7 +148,6 @@ public function testInvalidOptionType() $command->setCode(function (#[Option] ?object $any = null) {}); $this->expectException(LogicException::class); - $this->expectExceptionMessage('The type "object" of parameter "$any" is not supported as a command option. Only "string", "bool", "int", "float", "array" types are allowed.'); $command->getDefinition(); } @@ -322,13 +320,12 @@ public static function provideNonBinaryInputOptions(): \Generator /** * @dataProvider provideInvalidOptionDefinitions */ - public function testInvalidOptionDefinition(callable $code, string $expectedMessage) + public function testInvalidOptionDefinition(callable $code) { $command = new Command('foo'); $command->setCode($code); $this->expectException(LogicException::class); - $this->expectExceptionMessage($expectedMessage); $command->getDefinition(); } @@ -336,40 +333,31 @@ public function testInvalidOptionDefinition(callable $code, string $expectedMess public static function provideInvalidOptionDefinitions(): \Generator { yield 'no-default' => [ - function (#[Option] string $a) {}, - 'The option parameter "$a" must declare a default value.', + function (#[Option] string $a) {} ]; yield 'nullable-bool-default-true' => [ - function (#[Option] ?bool $a = true) {}, - 'The option parameter "$a" must not be nullable when it has a default boolean value.', + function (#[Option] ?bool $a = true) {} ]; yield 'nullable-bool-default-false' => [ - function (#[Option] ?bool $a = false) {}, - 'The option parameter "$a" must not be nullable when it has a default boolean value.', + function (#[Option] ?bool $a = false) {} ]; yield 'invalid-union-type' => [ - function (#[Option] array|bool $a = false) {}, - 'The union type for parameter "$a" is not supported as a command option. Only "bool|string", "bool|int", "bool|float" types are allowed.', + function (#[Option] array|bool $a = false) {} ]; yield 'union-type-cannot-allow-null' => [ function (#[Option] string|bool|null $a = null) {}, - 'The union type for parameter "$a" is not supported as a command option. Only "bool|string", "bool|int", "bool|float" types are allowed.', ]; yield 'union-type-default-true' => [ function (#[Option] string|bool $a = true) {}, - 'The option parameter "$a" must have a default value of false.', ]; yield 'union-type-default-string' => [ function (#[Option] string|bool $a = 'foo') {}, - 'The option parameter "$a" must have a default value of false.', ]; yield 'nullable-string-not-null-default' => [ function (#[Option] ?string $a = 'foo') {}, - 'The option parameter "$a" must either be not-nullable or have a default of null.', ]; yield 'nullable-array-not-null-default' => [ function (#[Option] ?array $a = []) {}, - 'The option parameter "$a" must either be not-nullable or have a default of null.', ]; } From 73ebb399a55861ef3b069191fc4c4d7aecc74da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Sat, 24 May 2025 16:05:12 +0200 Subject: [PATCH 51/57] [AssetMapper] Fix SequenceParser possible infinite loop --- .../Parser/JavascriptSequenceParser.php | 41 +++++++++---------- .../Parser/JavascriptSequenceParserTest.php | 5 +++ 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php b/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php index 943c0eea14f51..7531221a8e5ee 100644 --- a/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php +++ b/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php @@ -133,36 +133,35 @@ public function parseUntil(int $position): void continue; } - // Single-line string - if ('"' === $matchChar || "'" === $matchChar) { - if (false === $endPos = strpos($this->content, $matchChar, $matchPos + 1)) { - $this->endsWithSequence(self::STATE_STRING, $position); - - return; - } - while (false !== $endPos && '\\' == $this->content[$endPos - 1]) { - $endPos = strpos($this->content, $matchChar, $endPos + 1); + if ('"' === $matchChar || "'" === $matchChar || '`' === $matchChar) { + $endPos = $matchPos + 1; + while (false !== $endPos = strpos($this->content, $matchChar, $endPos)) { + $backslashes = 0; + $i = $endPos - 1; + while ($i >= 0 && $this->content[$i] === '\\') { + $backslashes++; + $i--; + } + + if (0 === $backslashes % 2) { + break; + } + + $endPos++; } - $this->cursor = min($endPos + 1, $position); - $this->setSequence(self::STATE_STRING, $endPos + 1); - continue; - } - - // Multi-line string - if ('`' === $matchChar) { - if (false === $endPos = strpos($this->content, $matchChar, $matchPos + 1)) { + if (false === $endPos) { $this->endsWithSequence(self::STATE_STRING, $position); - return; } - while (false !== $endPos && '\\' == $this->content[$endPos - 1]) { - $endPos = strpos($this->content, $matchChar, $endPos + 1); - } $this->cursor = min($endPos + 1, $position); $this->setSequence(self::STATE_STRING, $endPos + 1); + continue; } + + // Fallback + $this->cursor = $matchPos + 1; } } diff --git a/src/Symfony/Component/AssetMapper/Tests/Compiler/Parser/JavascriptSequenceParserTest.php b/src/Symfony/Component/AssetMapper/Tests/Compiler/Parser/JavascriptSequenceParserTest.php index cd9c88ff72593..794b7bbf61d94 100644 --- a/src/Symfony/Component/AssetMapper/Tests/Compiler/Parser/JavascriptSequenceParserTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/Compiler/Parser/JavascriptSequenceParserTest.php @@ -230,5 +230,10 @@ public static function provideStringCases(): iterable 3, false, ]; + yield 'after unclosed string' => [ + '"hello', + 6, + true, + ]; } } From 9fbc6a4914bfef64b02ae157f6310f643fe00faa Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 24 May 2025 16:28:13 +0200 Subject: [PATCH 52/57] [Uid] Remove InvalidU*idException in favor of InvalidArgumentException --- .../Uid/Exception/InvalidUlidException.php | 20 ----------------- .../Uid/Exception/InvalidUuidException.php | 22 ------------------- src/Symfony/Component/Uid/Tests/UlidTest.php | 3 +-- src/Symfony/Component/Uid/Ulid.php | 3 +-- src/Symfony/Component/Uid/Uuid.php | 6 ++--- 5 files changed, 5 insertions(+), 49 deletions(-) delete mode 100644 src/Symfony/Component/Uid/Exception/InvalidUlidException.php delete mode 100644 src/Symfony/Component/Uid/Exception/InvalidUuidException.php diff --git a/src/Symfony/Component/Uid/Exception/InvalidUlidException.php b/src/Symfony/Component/Uid/Exception/InvalidUlidException.php deleted file mode 100644 index cfb42ac5867a7..0000000000000 --- a/src/Symfony/Component/Uid/Exception/InvalidUlidException.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Uid\Exception; - -class InvalidUlidException extends InvalidArgumentException -{ - public function __construct(string $value) - { - parent::__construct(\sprintf('Invalid ULID: "%s".', $value)); - } -} diff --git a/src/Symfony/Component/Uid/Exception/InvalidUuidException.php b/src/Symfony/Component/Uid/Exception/InvalidUuidException.php deleted file mode 100644 index 97009412b9c63..0000000000000 --- a/src/Symfony/Component/Uid/Exception/InvalidUuidException.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Uid\Exception; - -class InvalidUuidException extends InvalidArgumentException -{ - public function __construct( - public readonly int $type, - string $value, - ) { - parent::__construct(\sprintf('Invalid UUID%s: "%s".', $type ? 'v'.$type : '', $value)); - } -} diff --git a/src/Symfony/Component/Uid/Tests/UlidTest.php b/src/Symfony/Component/Uid/Tests/UlidTest.php index fe1e15b4cedde..f34660fbfd393 100644 --- a/src/Symfony/Component/Uid/Tests/UlidTest.php +++ b/src/Symfony/Component/Uid/Tests/UlidTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Uid\Exception\InvalidArgumentException; -use Symfony\Component\Uid\Exception\InvalidUlidException; use Symfony\Component\Uid\MaxUlid; use Symfony\Component\Uid\NilUlid; use Symfony\Component\Uid\Tests\Fixtures\CustomUlid; @@ -43,7 +42,7 @@ public function testGenerate() public function testWithInvalidUlid() { - $this->expectException(InvalidUlidException::class); + $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid ULID: "this is not a ulid".'); new Ulid('this is not a ulid'); diff --git a/src/Symfony/Component/Uid/Ulid.php b/src/Symfony/Component/Uid/Ulid.php index 9170d429b0eb7..5ea3b84051880 100644 --- a/src/Symfony/Component/Uid/Ulid.php +++ b/src/Symfony/Component/Uid/Ulid.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Uid; use Symfony\Component\Uid\Exception\InvalidArgumentException; -use Symfony\Component\Uid\Exception\InvalidUlidException; /** * A ULID is lexicographically sortable and contains a 48-bit timestamp and 80-bit of crypto-random entropy. @@ -39,7 +38,7 @@ public function __construct(?string $ulid = null) $this->uid = $ulid; } else { if (!self::isValid($ulid)) { - throw new InvalidUlidException($ulid); + throw new InvalidArgumentException(\sprintf('Invalid ULID: "%s".', $ulid)); } $this->uid = strtoupper($ulid); diff --git a/src/Symfony/Component/Uid/Uuid.php b/src/Symfony/Component/Uid/Uuid.php index 66717f2ca1d2e..e1c9735ee85fe 100644 --- a/src/Symfony/Component/Uid/Uuid.php +++ b/src/Symfony/Component/Uid/Uuid.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Uid; -use Symfony\Component\Uid\Exception\InvalidUuidException; +use Symfony\Component\Uid\Exception\InvalidArgumentException; /** * @author Grégoire Pineau @@ -41,13 +41,13 @@ public function __construct(string $uuid, bool $checkVariant = false) $type = preg_match('{^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$}Di', $uuid) ? (int) $uuid[14] : false; if (false === $type || (static::TYPE ?: $type) !== $type) { - throw new InvalidUuidException(static::TYPE, $uuid); + throw new InvalidArgumentException(\sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid)); } $this->uid = strtolower($uuid); if ($checkVariant && !\in_array($this->uid[19], ['8', '9', 'a', 'b'], true)) { - throw new InvalidUuidException(static::TYPE, $uuid); + throw new InvalidArgumentException(\sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid)); } } From d775dde53475c95f17645436dadcb6df0b0d91cd Mon Sep 17 00:00:00 2001 From: HypeMC Date: Sat, 24 May 2025 22:22:45 +0200 Subject: [PATCH 53/57] [Routing] Fix inline default `null` --- src/Symfony/Component/Routing/Route.php | 2 +- .../Component/Routing/Tests/RouteTest.php | 71 +++++++++++-------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 1ed484f71237b..621a4239fcf7a 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -420,7 +420,7 @@ private function extractInlineDefaultsAndRequirements(string $pattern): string $pattern = preg_replace_callback('#\{(!?)([\w\x80-\xFF]++)(:([\w\x80-\xFF]++)(\.[\w\x80-\xFF]++)?)?(<.*?>)?(\?[^\}]*+)?\}#', function ($m) use (&$mapping) { if (isset($m[7][0])) { - $this->setDefault($m[2], '?' !== $m[6] ? substr($m[7], 1) : null); + $this->setDefault($m[2], '?' !== $m[7] ? substr($m[7], 1) : null); } if (isset($m[6][0])) { $this->setRequirement($m[2], substr($m[6], 1, -1)); diff --git a/src/Symfony/Component/Routing/Tests/RouteTest.php b/src/Symfony/Component/Routing/Tests/RouteTest.php index b58358a3ef31b..3472804249f57 100644 --- a/src/Symfony/Component/Routing/Tests/RouteTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteTest.php @@ -226,37 +226,48 @@ public function testSerialize() $this->assertNotSame($route, $unserialized); } - public function testInlineDefaultAndRequirement() + /** + * @dataProvider provideInlineDefaultAndRequirementCases + */ + public function testInlineDefaultAndRequirement(Route $route, string $expectedPath, string $expectedHost, array $expectedDefaults, array $expectedRequirements) + { + self::assertSame($expectedPath, $route->getPath()); + self::assertSame($expectedHost, $route->getHost()); + self::assertSame($expectedDefaults, $route->getDefaults()); + self::assertSame($expectedRequirements, $route->getRequirements()); + } + + public static function provideInlineDefaultAndRequirementCases(): iterable { - $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', null), new Route('/foo/{bar?}')); - $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?baz}')); - $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?baz}')); - $this->assertEquals((new Route('/foo/{!bar}'))->setDefault('bar', 'baz'), new Route('/foo/{!bar?baz}')); - $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?}', ['bar' => 'baz'])); - - $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '.*'), new Route('/foo/{bar<.*>}')); - $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '>'), new Route('/foo/{bar<>>}')); - $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '\d+'), new Route('/foo/{bar<.*>}', [], ['bar' => '\d+'])); - $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '[a-z]{2}'), new Route('/foo/{bar<[a-z]{2}>}')); - $this->assertEquals((new Route('/foo/{!bar}'))->setRequirement('bar', '\d+'), new Route('/foo/{!bar<\d+>}')); - - $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', null)->setRequirement('bar', '.*'), new Route('/foo/{bar<.*>?}')); - $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', '<>')->setRequirement('bar', '>'), new Route('/foo/{bar<>>?<>}')); - - $this->assertEquals((new Route('/{foo}/{!bar}'))->setDefaults(['bar' => '<>', 'foo' => '\\'])->setRequirements(['bar' => '\\', 'foo' => '.']), new Route('/{foo<.>?\}/{!bar<\>?<>}')); - - $this->assertEquals((new Route('/'))->setHost('{bar}')->setDefault('bar', null), (new Route('/'))->setHost('{bar?}')); - $this->assertEquals((new Route('/'))->setHost('{bar}')->setDefault('bar', 'baz'), (new Route('/'))->setHost('{bar?baz}')); - $this->assertEquals((new Route('/'))->setHost('{bar}')->setDefault('bar', 'baz'), (new Route('/'))->setHost('{bar?baz}')); - $this->assertEquals((new Route('/'))->setHost('{bar}')->setDefault('bar', null), (new Route('/', ['bar' => 'baz']))->setHost('{bar?}')); - - $this->assertEquals((new Route('/'))->setHost('{bar}')->setRequirement('bar', '.*'), (new Route('/'))->setHost('{bar<.*>}')); - $this->assertEquals((new Route('/'))->setHost('{bar}')->setRequirement('bar', '>'), (new Route('/'))->setHost('{bar<>>}')); - $this->assertEquals((new Route('/'))->setHost('{bar}')->setRequirement('bar', '.*'), (new Route('/', [], ['bar' => '\d+']))->setHost('{bar<.*>}')); - $this->assertEquals((new Route('/'))->setHost('{bar}')->setRequirement('bar', '[a-z]{2}'), (new Route('/'))->setHost('{bar<[a-z]{2}>}')); - - $this->assertEquals((new Route('/'))->setHost('{bar}')->setDefault('bar', null)->setRequirement('bar', '.*'), (new Route('/'))->setHost('{bar<.*>?}')); - $this->assertEquals((new Route('/'))->setHost('{bar}')->setDefault('bar', '<>')->setRequirement('bar', '>'), (new Route('/'))->setHost('{bar<>>?<>}')); + yield [new Route('/foo/{bar?}'), '/foo/{bar}', '', ['bar' => null], []]; + yield [new Route('/foo/{bar?baz}'), '/foo/{bar}', '', ['bar' => 'baz'], []]; + yield [new Route('/foo/{bar?baz}'), '/foo/{bar}', '', ['bar' => 'baz'], []]; + yield [new Route('/foo/{!bar?baz}'), '/foo/{!bar}', '', ['bar' => 'baz'], []]; + yield [new Route('/foo/{bar?}', ['bar' => 'baz']), '/foo/{bar}', '', ['bar' => 'baz'], []]; + + yield [new Route('/foo/{bar<.*>}'), '/foo/{bar}', '', [], ['bar' => '.*']]; + yield [new Route('/foo/{bar<>>}'), '/foo/{bar}', '', [], ['bar' => '>']]; + yield [new Route('/foo/{bar<.*>}', [], ['bar' => '\d+']), '/foo/{bar}', '', [], ['bar' => '\d+']]; + yield [new Route('/foo/{bar<[a-z]{2}>}'), '/foo/{bar}', '', [], ['bar' => '[a-z]{2}']]; + yield [new Route('/foo/{!bar<\d+>}'), '/foo/{!bar}', '', [], ['bar' => '\d+']]; + + yield [new Route('/foo/{bar<.*>?}'), '/foo/{bar}', '', ['bar' => null], ['bar' => '.*']]; + yield [new Route('/foo/{bar<>>?<>}'), '/foo/{bar}', '', ['bar' => '<>'], ['bar' => '>']]; + + yield [new Route('/{foo<.>?\}/{!bar<\>?<>}'), '/{foo}/{!bar}', '', ['foo' => '\\', 'bar' => '<>'], ['foo' => '.', 'bar' => '\\']]; + + yield [new Route('/', host: '{bar?}'), '/', '{bar}', ['bar' => null], []]; + yield [new Route('/', host: '{bar?baz}'), '/', '{bar}', ['bar' => 'baz'], []]; + yield [new Route('/', host: '{bar?baz}'), '/', '{bar}', ['bar' => 'baz'], []]; + yield [new Route('/', ['bar' => 'baz'], host: '{bar?}'), '/', '{bar}', ['bar' => null], []]; + + yield [new Route('/', host: '{bar<.*>}'), '/', '{bar}', [], ['bar' => '.*']]; + yield [new Route('/', host: '{bar<>>}'), '/', '{bar}', [], ['bar' => '>']]; + yield [new Route('/', [], ['bar' => '\d+'], host: '{bar<.*>}'), '/', '{bar}', [], ['bar' => '.*']]; + yield [new Route('/', host: '{bar<[a-z]{2}>}'), '/', '{bar}', [], ['bar' => '[a-z]{2}']]; + + yield [new Route('/', host: '{bar<.*>?}'), '/', '{bar}', ['bar' => null], ['bar' => '.*']]; + yield [new Route('/', host: '{bar<>>?<>}'), '/', '{bar}', ['bar' => '<>'], ['bar' => '>']]; } /** From 71528ca67f15bb43456fef36118cb161063c9839 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 May 2025 23:27:21 +0200 Subject: [PATCH 54/57] conflict with 7.4 releases of experimental components --- src/Symfony/Bundle/FrameworkBundle/composer.json | 1 + src/Symfony/Component/JsonPath/composer.json | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 316c595ffa2bb..15a9496d11067 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -94,6 +94,7 @@ "symfony/mailer": "<6.4", "symfony/messenger": "<6.4", "symfony/mime": "<6.4", + "symfony/object-mapper": ">=7.4", "symfony/property-info": "<6.4", "symfony/property-access": "<6.4", "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", diff --git a/src/Symfony/Component/JsonPath/composer.json b/src/Symfony/Component/JsonPath/composer.json index 95b02675e7459..fe8ddf84dd82d 100644 --- a/src/Symfony/Component/JsonPath/composer.json +++ b/src/Symfony/Component/JsonPath/composer.json @@ -20,7 +20,10 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/json-streamer": "^7.3" + "symfony/json-streamer": "7.3.*" + }, + "conflict": { + "symfony/json-streamer": ">=7.4" }, "autoload": { "psr-4": { "Symfony\\Component\\JsonPath\\": "" }, From 5972d989e2942e43faad54a3608a54ff146a3d5a Mon Sep 17 00:00:00 2001 From: HypeMC Date: Sun, 25 May 2025 03:39:50 +0200 Subject: [PATCH 55/57] [DoctrineBridge] Fix resetting the manager when using native lazy objects --- .../Bridge/Doctrine/ManagerRegistry.php | 42 ++++++++----- .../Doctrine/Tests/Fixtures/DummyManager.php | 13 ++++ .../Doctrine/Tests/ManagerRegistryTest.php | 62 +++++++++++++++++-- 3 files changed, 99 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index a533b3bb8d12c..fa4d88b99455d 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -80,21 +80,35 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { return; } - try { - $r->resetAsLazyProxy($manager, \Closure::bind( - function () use ($name) { - $name = $this->aliases[$name] ?? $name; + $asProxy = $r->initializeLazyObject($manager) !== $manager; + $initializer = \Closure::bind( + function ($manager) use ($name, $asProxy) { + $name = $this->aliases[$name] ?? $name; + if ($asProxy) { + $manager = false; + } + + $manager = match (true) { + isset($this->fileMap[$name]) => $this->load($this->fileMap[$name], $manager), + !$method = $this->methodMap[$name] ?? null => throw new \LogicException(\sprintf('The "%s" service is synthetic and cannot be reset.', $name)), + (new \ReflectionMethod($this, $method))->isStatic() => $this->{$method}($this, $manager), + default => $this->{$method}($manager), + }; + + if ($asProxy) { + return $manager; + } + }, + $this->container, + Container::class + ); - return match (true) { - isset($this->fileMap[$name]) => $this->load($this->fileMap[$name], false), - !$method = $this->methodMap[$name] ?? null => throw new \LogicException(\sprintf('The "%s" service is synthetic and cannot be reset.', $name)), - (new \ReflectionMethod($this, $method))->isStatic() => $this->{$method}($this, false), - default => $this->{$method}(false), - }; - }, - $this->container, - Container::class - )); + try { + if ($asProxy) { + $r->resetAsLazyProxy($manager, $initializer); + } else { + $r->resetAsLazyGhost($manager, $initializer); + } } catch (\Error $e) { if (__FILE__ !== $e->getFile()) { throw $e; diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php index 04e5a2acdd334..806ef032d8d5c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/DummyManager.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Bridge\Doctrine\Tests\Fixtures; use Doctrine\Persistence\Mapping\ClassMetadata; @@ -11,6 +20,10 @@ class DummyManager implements ObjectManager { public $bar; + public function __construct() + { + } + public function find($className, $id): ?object { } diff --git a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php index fa44ba0a00bbb..4803e6acaf0af 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php @@ -22,7 +22,7 @@ class ManagerRegistryTest extends TestCase { - public static function setUpBeforeClass(): void + public function testResetService() { $container = new ContainerBuilder(); @@ -32,10 +32,7 @@ public static function setUpBeforeClass(): void $dumper = new PhpDumper($container); eval('?>'.$dumper->dump(['class' => 'LazyServiceDoctrineBridgeContainer'])); - } - public function testResetService() - { $container = new \LazyServiceDoctrineBridgeContainer(); $registry = new TestManagerRegistry('name', [], ['defaultManager' => 'foo'], 'defaultConnection', 'defaultManager', 'proxyInterfaceName'); @@ -52,6 +49,63 @@ public function testResetService() $this->assertFalse(isset($foo->bar)); } + /** + * @requires PHP 8.4 + * + * @dataProvider provideResetServiceWithNativeLazyObjectsCases + */ + public function testResetServiceWithNativeLazyObjects(string $class) + { + $container = new $class(); + + $registry = new TestManagerRegistry( + 'irrelevant', + [], + ['defaultManager' => 'foo'], + 'irrelevant', + 'defaultManager', + 'irrelevant', + ); + $registry->setTestContainer($container); + + $foo = $container->get('foo'); + self::assertSame(DummyManager::class, $foo::class); + + $foo->bar = 123; + self::assertTrue(isset($foo->bar)); + + $registry->resetManager(); + + self::assertSame($foo, $container->get('foo')); + self::assertSame(DummyManager::class, $foo::class); + self::assertFalse(isset($foo->bar)); + } + + public static function provideResetServiceWithNativeLazyObjectsCases(): iterable + { + $container = new ContainerBuilder(); + + $container->register('foo', DummyManager::class)->setPublic(true); + $container->getDefinition('foo')->setLazy(true); + $container->compile(); + + $dumper = new PhpDumper($container); + + eval('?>'.$dumper->dump(['class' => 'NativeLazyServiceDoctrineBridgeContainer'])); + + yield ['NativeLazyServiceDoctrineBridgeContainer']; + + $dumps = $dumper->dump(['class' => 'NativeLazyServiceDoctrineBridgeContainerAsFiles', 'as_files' => true]); + + $lastDump = array_pop($dumps); + foreach (array_reverse($dumps) as $dump) { + eval('?>'.$dump); + } + eval('?>'.$lastDump); + + yield ['NativeLazyServiceDoctrineBridgeContainerAsFiles']; + } + /** * When performing an entity manager lazy service reset, the reset operations may re-use the container * to create a "fresh" service: when doing so, it can happen that the "fresh" service is itself a proxy. From a3d3dff6229fd37fce8fedbd9189c6dcd77d3d2f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 25 May 2025 22:29:28 +0200 Subject: [PATCH 56/57] Update CHANGELOG for 7.3.0-RC1 --- CHANGELOG-7.3.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG-7.3.md b/CHANGELOG-7.3.md index b88c6a58f068c..91adc8732cd35 100644 --- a/CHANGELOG-7.3.md +++ b/CHANGELOG-7.3.md @@ -7,6 +7,36 @@ in 7.3 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/v7.3.0...v7.3.1 +* 7.3.0-RC1 (2025-05-25) + + * bug #60529 [AssetMapper] Fix SequenceParser possible infinite loop (smnandre) + * bug #60532 [Routing] Fix inline default `null` (HypeMC) + * bug #60535 [DoctrineBridge] Fix resetting the manager when using native lazy objects (HypeMC) + * bug #60500 [PhpUnitBridge] Fix cleaning up mocked features with attributes (HypeMC) + * bug #60330 [FrameworkBundle] skip messenger deduplication middleware registration when no "default" lock is configured (lyrixx) + * bug #60494 [Messenger] fix: Add argument as integer (overexpOG) + * bug #60524 [Notifier] Fix Clicksend transport (BafS) + * bug #60479 [FrameworkBundle] object mapper service definition without form (soyuka) + * bug #60478 [Validator] add missing `$extensions` and `$extensionsMessage` to the `Image` constraint (xabbuh) + * bug #60491 [ObjectMapper] added earlier skip to allow if=false when using source mapping (maciekpaprocki) + * bug #60484 [PhpUnitBridge] Clean up mocked features only when ``@group`` is present (HypeMC) + * bug #60490 [PhpUnitBridge] set path to the PHPUnit autoload file (xabbuh) + * bug #60489 [FrameworkBundle] Fix activation strategy of traceable decorators (nicolas-grekas) + * feature #60475 [Validator] Revert Slug constraint (wouterj) + * feature #60105 [JsonPath] Add `JsonPathAssertionsTrait` and related constraints (alexandre-daubois) + * bug #60423 [DependencyInjection] Make `DefinitionErrorExceptionPass` consider `IGNORE_ON_UNINITIALIZED_REFERENCE` and `RUNTIME_EXCEPTION_ON_INVALID_REFERENCE` the same (MatTheCat) + * bug #60439 [FrameworkBundle] Fix declaring field-attr tags in xml config files (nicolas-grekas) + * bug #60428 [DependencyInjection] Fix missing binding for ServiceCollectionInterface when declaring a service subscriber (nicolas-grekas) + * bug #60426 [Validator] let the `SlugValidator` accept `AsciiSlugger` results (xabbuh) + * bug #60421 [VarExporter] Fixed lazy-loading ghost objects generation with property hooks (cheack) + * bug #60419 [SecurityBundle] normalize string values to a single ExposeSecurityLevel instance (xabbuh) + * bug #60266 [Security] Exclude remember_me from default login authenticators (santysisi) + * bug #60407 [Console] Invokable command `#[Option]` adjustments (kbond) + * bug #60400 [Config] Fix generated comment for multiline "info" (GromNaN) + * bug #60260 [Serializer] Prevent `Cannot traverse an already closed generator` error by materializing Traversable input (santysisi) + * bug #60292 [HttpFoundation] Encode path in `X-Accel-Redirect` header (Athorcis) + * bug #60401 Passing more than one Security attribute is not supported (santysisi) + * 7.3.0-BETA2 (2025-05-10) * bug #58643 [SecurityBundle] Use Composer `InstalledVersions` to check if flex is installed (andyexeter) From f3605bbc8887af1221798b1dc7173c49d5d980aa Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 25 May 2025 22:29:38 +0200 Subject: [PATCH 57/57] Update VERSION for 7.3.0-RC1 --- 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 b5a41236d1899..566e721bf3bb3 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -73,12 +73,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '7.3.0-DEV'; + public const VERSION = '7.3.0-RC1'; public const VERSION_ID = 70300; public const MAJOR_VERSION = 7; public const MINOR_VERSION = 3; public const RELEASE_VERSION = 0; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = 'RC1'; public const END_OF_MAINTENANCE = '05/2025'; public const END_OF_LIFE = '01/2026'; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy