From 0acd4030272355c909e29430022e1d6399367997 Mon Sep 17 00:00:00 2001 From: Alexandre Daubois Date: Fri, 23 Jun 2023 16:03:28 +0200 Subject: [PATCH 01/55] [DoctrineBridge] Ignore invalid stores in `LockStoreSchemaListener` raised by `StoreFactory` --- .../SchemaListener/LockStoreSchemaListener.php | 17 +++++++++++++---- .../LockStoreSchemaListenerTest.php | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/SchemaListener/LockStoreSchemaListener.php b/src/Symfony/Bridge/Doctrine/SchemaListener/LockStoreSchemaListener.php index 0902b376d8968..5ab591d318225 100644 --- a/src/Symfony/Bridge/Doctrine/SchemaListener/LockStoreSchemaListener.php +++ b/src/Symfony/Bridge/Doctrine/SchemaListener/LockStoreSchemaListener.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Doctrine\SchemaListener; use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; +use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\PersistingStoreInterface; use Symfony\Component\Lock\Store\DoctrineDbalStore; @@ -28,12 +29,20 @@ public function postGenerateSchema(GenerateSchemaEventArgs $event): void { $connection = $event->getEntityManager()->getConnection(); - foreach ($this->stores as $store) { - if (!$store instanceof DoctrineDbalStore) { - continue; + $storesIterator = new \ArrayIterator($this->stores); + while ($storesIterator->valid()) { + try { + $store = $storesIterator->current(); + if (!$store instanceof DoctrineDbalStore) { + continue; + } + + $store->configureSchema($event->getSchema(), $this->getIsSameDatabaseChecker($connection)); + } catch (InvalidArgumentException) { + // no-op } - $store->configureSchema($event->getSchema(), $this->getIsSameDatabaseChecker($connection)); + $storesIterator->next(); } } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php index d8d06a5fe0524..6f23d680feb9f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/SchemaListener/LockStoreSchemaListenerTest.php @@ -17,6 +17,7 @@ use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\SchemaListener\LockStoreSchemaListener; +use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Store\DoctrineDbalStore; class LockStoreSchemaListenerTest extends TestCase @@ -39,4 +40,20 @@ public function testPostGenerateSchemaLockPdo() $subscriber = new LockStoreSchemaListener([$lockStore]); $subscriber->postGenerateSchema($event); } + + public function testPostGenerateSchemaWithInvalidLockStore() + { + $entityManager = $this->createMock(EntityManagerInterface::class); + $entityManager->expects($this->once()) + ->method('getConnection') + ->willReturn($this->createMock(Connection::class)); + $event = new GenerateSchemaEventArgs($entityManager, new Schema()); + + $subscriber = new LockStoreSchemaListener((static function (): \Generator { + yield $this->createMock(DoctrineDbalStore::class); + + throw new InvalidArgumentException('Unsupported Connection'); + })()); + $subscriber->postGenerateSchema($event); + } } From 2f04a649a87b32a5b74bc9b60702d220c8d62162 Mon Sep 17 00:00:00 2001 From: valtzu Date: Wed, 23 Aug 2023 22:48:50 +0300 Subject: [PATCH 02/55] Fix missing stamps in delayed message handling --- .../DelayedMessageHandlingException.php | 12 ++- .../DispatchAfterCurrentBusMiddleware.php | 2 +- .../Tests/FailureIntegrationTest.php | 86 +++++++++++++++++++ src/Symfony/Component/Messenger/Worker.php | 3 +- 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Messenger/Exception/DelayedMessageHandlingException.php b/src/Symfony/Component/Messenger/Exception/DelayedMessageHandlingException.php index 6934562bda05f..3baafda76e3b9 100644 --- a/src/Symfony/Component/Messenger/Exception/DelayedMessageHandlingException.php +++ b/src/Symfony/Component/Messenger/Exception/DelayedMessageHandlingException.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Messenger\Exception; +use Symfony\Component\Messenger\Envelope; + /** * When handling queued messages from {@link DispatchAfterCurrentBusMiddleware}, * some handlers caused an exception. This exception contains all those handler exceptions. @@ -20,9 +22,12 @@ class DelayedMessageHandlingException extends RuntimeException { private array $exceptions; + private Envelope $envelope; - public function __construct(array $exceptions) + public function __construct(array $exceptions, Envelope $envelope) { + $this->envelope = $envelope; + $exceptionMessages = implode(", \n", array_map( fn (\Throwable $e) => $e::class.': '.$e->getMessage(), $exceptions @@ -43,4 +48,9 @@ public function getExceptions(): array { return $this->exceptions; } + + public function getEnvelope(): Envelope + { + return $this->envelope; + } } diff --git a/src/Symfony/Component/Messenger/Middleware/DispatchAfterCurrentBusMiddleware.php b/src/Symfony/Component/Messenger/Middleware/DispatchAfterCurrentBusMiddleware.php index bc5618af8d2a4..1842b35b6a10e 100644 --- a/src/Symfony/Component/Messenger/Middleware/DispatchAfterCurrentBusMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/DispatchAfterCurrentBusMiddleware.php @@ -97,7 +97,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $this->isRootDispatchCallRunning = false; if (\count($exceptions) > 0) { - throw new DelayedMessageHandlingException($exceptions); + throw new DelayedMessageHandlingException($exceptions, $returnedEnvelope); } return $returnedEnvelope; diff --git a/src/Symfony/Component/Messenger/Tests/FailureIntegrationTest.php b/src/Symfony/Component/Messenger/Tests/FailureIntegrationTest.php index a41ee33ac72af..473916aa0106b 100644 --- a/src/Symfony/Component/Messenger/Tests/FailureIntegrationTest.php +++ b/src/Symfony/Component/Messenger/Tests/FailureIntegrationTest.php @@ -22,14 +22,19 @@ use Symfony\Component\Messenger\EventListener\SendFailedMessageForRetryListener; use Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener; use Symfony\Component\Messenger\EventListener\StopWorkerOnMessageLimitListener; +use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException; use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\Handler\HandlerDescriptor; use Symfony\Component\Messenger\Handler\HandlersLocator; use Symfony\Component\Messenger\MessageBus; +use Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware; +use Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware; use Symfony\Component\Messenger\Middleware\FailedMessageProcessingMiddleware; use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware; use Symfony\Component\Messenger\Middleware\SendMessageMiddleware; use Symfony\Component\Messenger\Retry\MultiplierRetryStrategy; +use Symfony\Component\Messenger\Stamp\BusNameStamp; +use Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp; use Symfony\Component\Messenger\Stamp\ErrorDetailsStamp; use Symfony\Component\Messenger\Stamp\SentToFailureTransportStamp; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; @@ -354,6 +359,87 @@ public function testMultipleFailedTransportsWithoutGlobalFailureTransport() // After the message fails again, the message is discarded from the "the_failure_transport2" $this->assertCount(0, $failureTransport2->getMessagesWaitingToBeReceived()); } + + public function testStampsAddedByMiddlewaresDontDisappearWhenDelayedMessageFails() + { + $transport1 = new DummyFailureTestSenderAndReceiver(); + + $transports = [ + 'transport1' => $transport1, + ]; + + $locator = $this->createMock(ContainerInterface::class); + $locator->expects($this->any()) + ->method('has') + ->willReturn(true); + $locator->expects($this->any()) + ->method('get') + ->willReturnCallback(fn ($transportName) => $transports[$transportName]); + $senderLocator = new SendersLocator([], $locator); + + $retryStrategyLocator = $this->createMock(ContainerInterface::class); + $retryStrategyLocator->expects($this->any()) + ->method('has') + ->willReturn(true); + $retryStrategyLocator->expects($this->any()) + ->method('get') + ->willReturn(new MultiplierRetryStrategy(1)); + + $syncHandlerThatFails = new DummyTestHandler(true); + + $middlewareStack = new \ArrayIterator([ + new AddBusNameStampMiddleware('some.bus'), + new DispatchAfterCurrentBusMiddleware(), + new SendMessageMiddleware($senderLocator), + ]); + + $bus = new MessageBus($middlewareStack); + + $transport1Handler = fn () => $bus->dispatch(new \stdClass(), [new DispatchAfterCurrentBusStamp()]); + + $handlerLocator = new HandlersLocator([ + DummyMessage::class => [new HandlerDescriptor($transport1Handler)], + \stdClass::class => [new HandlerDescriptor($syncHandlerThatFails)], + ]); + + $middlewareStack->append(new HandleMessageMiddleware($handlerLocator)); + + $dispatcher = new EventDispatcher(); + + $dispatcher->addSubscriber(new SendFailedMessageForRetryListener($locator, $retryStrategyLocator)); + $dispatcher->addSubscriber(new StopWorkerOnMessageLimitListener(1)); + + $runWorker = function (string $transportName) use ($transports, $bus, $dispatcher): ?\Throwable { + $throwable = null; + $failedListener = function (WorkerMessageFailedEvent $event) use (&$throwable) { + $throwable = $event->getThrowable(); + }; + $dispatcher->addListener(WorkerMessageFailedEvent::class, $failedListener); + + $worker = new Worker([$transportName => $transports[$transportName]], $bus, $dispatcher); + + $worker->run(); + + $dispatcher->removeListener(WorkerMessageFailedEvent::class, $failedListener); + + return $throwable; + }; + + // Simulate receive from external source + $transport1->send(new Envelope(new DummyMessage('API'))); + + // Receive the message from "transport1" + $throwable = $runWorker('transport1'); + + $this->assertInstanceOf(DelayedMessageHandlingException::class, $throwable, $throwable->getMessage()); + $this->assertSame(1, $syncHandlerThatFails->getTimesCalled()); + + $messagesWaiting = $transport1->getMessagesWaitingToBeReceived(); + + // Stamps should not be dropped on message that's queued for retry + $this->assertCount(1, $messagesWaiting); + $this->assertSame('some.bus', $messagesWaiting[0]->last(BusNameStamp::class)?->getBusName()); + } } class DummyFailureTestSenderAndReceiver implements ReceiverInterface, SenderInterface diff --git a/src/Symfony/Component/Messenger/Worker.php b/src/Symfony/Component/Messenger/Worker.php index 606d4bbd387a2..103dbf5d93e78 100644 --- a/src/Symfony/Component/Messenger/Worker.php +++ b/src/Symfony/Component/Messenger/Worker.php @@ -22,6 +22,7 @@ use Symfony\Component\Messenger\Event\WorkerRunningEvent; use Symfony\Component\Messenger\Event\WorkerStartedEvent; use Symfony\Component\Messenger\Event\WorkerStoppedEvent; +use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException; use Symfony\Component\Messenger\Exception\HandlerFailedException; use Symfony\Component\Messenger\Exception\RejectRedeliveredMessageException; use Symfony\Component\Messenger\Exception\RuntimeException; @@ -186,7 +187,7 @@ private function ack(): bool $receiver->reject($envelope); } - if ($e instanceof HandlerFailedException) { + if ($e instanceof HandlerFailedException || $e instanceof DelayedMessageHandlingException) { $envelope = $e->getEnvelope(); } From 70bb6801814693885a4caa6f03a768e3ba5f2497 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 26 Aug 2023 15:59:05 +0200 Subject: [PATCH 03/55] Bump Symfony version to 6.3.5 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index af4000b822d4a..94e886b49f63c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -76,12 +76,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.3.4'; - public const VERSION_ID = 60304; + public const VERSION = '6.3.5-DEV'; + public const VERSION_ID = 60305; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 3; - public const RELEASE_VERSION = 4; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 5; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '01/2024'; public const END_OF_LIFE = '01/2024'; From 9df0a3f1a256c6f4fb2d8ab5253af689a3fe663f Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Sun, 27 Aug 2023 15:16:37 +0200 Subject: [PATCH 04/55] [Security] Remove isAuthenticated and setAuthenticated token methods in tests --- .../Security/Http/Tests/Firewall/ContextListenerTest.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 64052062d00f5..c52aea62da43e 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -563,15 +563,6 @@ public function getUserIdentifier(): string return $this->getUserIdentifier(); } - public function isAuthenticated(): bool - { - return true; - } - - public function setAuthenticated(bool $isAuthenticated) - { - } - public function eraseCredentials(): void { } From 76f2433fa9d3db293c142d05bd712a40eb6621be Mon Sep 17 00:00:00 2001 From: valtzu Date: Mon, 28 Aug 2023 19:35:58 +0300 Subject: [PATCH 05/55] Fix routing to multiple fallback transports --- .../Tests/Transport/Sender/SendersLocatorTest.php | 6 ++++-- .../Messenger/Transport/Sender/SendersLocator.php | 12 ++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php index 4d9697eeaccc1..6b005cfd86e27 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Sender/SendersLocatorTest.php @@ -56,17 +56,19 @@ public function testSendersMapWithFallback() { $firstSender = $this->createMock(SenderInterface::class); $secondSender = $this->createMock(SenderInterface::class); + $thirdSender = $this->createMock(SenderInterface::class); $sendersLocator = $this->createContainer([ 'first' => $firstSender, 'second' => $secondSender, + 'third' => $thirdSender, ]); $locator = new SendersLocator([ DummyMessage::class => ['first'], - '*' => ['second'], + '*' => ['second', 'third'], ], $sendersLocator); $this->assertSame(['first' => $firstSender], iterator_to_array($locator->getSenders(new Envelope(new DummyMessage('a')))), 'Unexpected senders for configured message'); - $this->assertSame(['second' => $secondSender], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage()))), 'Unexpected senders for unconfigured message'); + $this->assertSame(['second' => $secondSender, 'third' => $thirdSender], iterator_to_array($locator->getSenders(new Envelope(new SecondMessage()))), 'Unexpected senders for unconfigured message'); } private function createContainer(array $senders): ContainerInterface diff --git a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php index 3420a6cc6043a..f8308ada3e2d2 100644 --- a/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php +++ b/src/Symfony/Component/Messenger/Transport/Sender/SendersLocator.php @@ -50,13 +50,13 @@ public function getSenders(Envelope $envelope): iterable $seen = []; foreach (HandlersLocator::listTypes($envelope) as $type) { - foreach ($this->sendersMap[$type] ?? [] as $senderAlias) { - if (str_ends_with($type, '*') && $seen) { - // the '*' acts as a fallback, if other senders already matched - // with previous types, skip the senders bound to the fallback - continue; - } + if (str_ends_with($type, '*') && $seen) { + // the '*' acts as a fallback, if other senders already matched + // with previous types, skip the senders bound to the fallback + continue; + } + foreach ($this->sendersMap[$type] ?? [] as $senderAlias) { if (!\in_array($senderAlias, $seen, true)) { $seen[] = $senderAlias; From aaf507a766cfb2b63152f3cc5c89e0d11c2ed00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Despont?= Date: Tue, 29 Aug 2023 08:36:24 +0200 Subject: [PATCH 06/55] Update Pbkdf2PasswordHasher.php Because https://www.php.net/manual/en/function.hash-pbkdf2.php is expecting string and not ?string. Pertmits avoiding deprecation warning. --- .../Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php b/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php index 57fbe0728fe93..2fc762cb4e870 100644 --- a/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php +++ b/src/Symfony/Component/PasswordHasher/Hasher/Pbkdf2PasswordHasher.php @@ -69,7 +69,7 @@ public function hash(string $plainPassword, string $salt = null): string throw new LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm)); } - $digest = hash_pbkdf2($this->algorithm, $plainPassword, $salt, $this->iterations, $this->length, true); + $digest = hash_pbkdf2($this->algorithm, $plainPassword, $salt ?? '', $this->iterations, $this->length, true); return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest); } From ee8f79ea5775d00846916f2c553823b42e08c162 Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Sun, 27 Aug 2023 14:49:05 +0200 Subject: [PATCH 07/55] Update phpdoc to not reference removed classes --- .../DependencyInjection/Security/Factory/AbstractFactory.php | 3 --- .../Authentication/AuthenticationFailureHandlerInterface.php | 4 +--- .../Component/Security/Http/Firewall/LogoutListener.php | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php index 24eb1377c51c2..f82b46217e5a4 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php @@ -16,9 +16,6 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; /** - * AbstractFactory is the base class for all classes inheriting from - * AbstractAuthenticationListener. - * * @author Fabien Potencier * @author Lukas Kahwe Smith * @author Johannes M. Schmitt diff --git a/src/Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php b/src/Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php index 6f6cffef1a06e..faf5979c28526 100644 --- a/src/Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php +++ b/src/Symfony/Component/Security/Http/Authentication/AuthenticationFailureHandlerInterface.php @@ -27,9 +27,7 @@ interface AuthenticationFailureHandlerInterface { /** - * This is called when an interactive authentication attempt fails. This is - * called by authentication listeners inheriting from - * AbstractAuthenticationListener. + * This is called when an interactive authentication attempt fails. */ public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response; } diff --git a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php index 885a0a1eb445b..77810524ef5c6 100644 --- a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php @@ -66,7 +66,7 @@ public function supports(Request $request): ?bool * validate the request. * * @throws LogoutException if the CSRF token is invalid - * @throws \RuntimeException if the LogoutSuccessHandlerInterface instance does not return a response + * @throws \RuntimeException if the LogoutEvent listener does not set a response */ public function authenticate(RequestEvent $event): void { From 3225112b7668cd394847542bdb0787218ae1a745 Mon Sep 17 00:00:00 2001 From: Owen Gray Date: Thu, 31 Aug 2023 12:22:10 -0400 Subject: [PATCH 08/55] fix parsing of payload timestamp to DateTimeImmutable --- .../Bridge/Mailgun/RemoteEvent/MailgunPayloadConverter.php | 4 ++-- .../Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/clicks.php | 2 +- .../Mailgun/Tests/Webhook/Fixtures/delivered_messages.json | 2 +- .../Mailgun/Tests/Webhook/Fixtures/delivered_messages.php | 2 +- .../Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/opens.php | 2 +- .../Mailgun/Tests/Webhook/Fixtures/permanent_failure.php | 2 +- .../Bridge/Mailgun/Tests/Webhook/Fixtures/spam_complaints.php | 2 +- .../Mailgun/Tests/Webhook/Fixtures/suppression_failure.php | 2 +- .../Mailgun/Tests/Webhook/Fixtures/temporary_failure.php | 2 +- .../Bridge/Mailgun/Tests/Webhook/Fixtures/unsubscribes.php | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/RemoteEvent/MailgunPayloadConverter.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/RemoteEvent/MailgunPayloadConverter.php index 7f1e52477d8ff..cb3f323861030 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/RemoteEvent/MailgunPayloadConverter.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/RemoteEvent/MailgunPayloadConverter.php @@ -50,8 +50,8 @@ public function convert(array $payload): AbstractMailerEvent }; $event = new MailerEngagementEvent($name, $payload['id'], $payload); } - if (!$date = \DateTimeImmutable::createFromFormat('U.u', $payload['timestamp'])) { - throw new ParseException(sprintf('Invalid date "%s".', $payload['timestamp'])); + if (!$date = \DateTimeImmutable::createFromFormat('U.u', sprintf('%.6F', $payload['timestamp']))) { + throw new ParseException(sprintf('Invalid date "%s".', sprintf('%.6F', $payload['timestamp']))); } $event->setDate($date); $event->setRecipientEmail($payload['recipient']); diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/clicks.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/clicks.php index cd556e6d26168..9aac4c899d6b9 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/clicks.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/clicks.php @@ -6,6 +6,6 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521243339.873676)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521243339.873676')); return $wh; diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.json b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.json index 1b0e4046b3ded..58700a5eb3c64 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.json +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.json @@ -6,7 +6,7 @@ }, "event-data": { "id": "CPgfbmQMTCKtHW6uIWtuVe", - "timestamp": 1521472262.908181, + "timestamp": 1521472262.000002, "log-level": "info", "event": "delivered", "delivery-status": { diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.php index 7240b90a96ef2..efb215d5f9fab 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/delivered_messages.php @@ -6,7 +6,7 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521472262.908181)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521472262.000002')); $wh->setReason('OK'); return $wh; diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/opens.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/opens.php index f224ca13bd78c..da8132ae3d747 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/opens.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/opens.php @@ -6,6 +6,6 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521243339.873676)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521243339.873676')); return $wh; diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/permanent_failure.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/permanent_failure.php index 51798f3ce77b7..8dfffd0362e85 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/permanent_failure.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/permanent_failure.php @@ -6,7 +6,7 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521233195.375624)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521233195.375624')); $wh->setReason('No Such User Here'); return $wh; diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/spam_complaints.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/spam_complaints.php index 224a79dc3fb41..4695a876849e9 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/spam_complaints.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/spam_complaints.php @@ -6,6 +6,6 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521233123.501324)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521233123.501324')); return $wh; diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/suppression_failure.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/suppression_failure.php index f5bb1a4d0c407..e24946dae9bd7 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/suppression_failure.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/suppression_failure.php @@ -6,7 +6,7 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521233195.375624)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521233195.375624')); $wh->setReason('Not delivering to previously bounced address'); return $wh; diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/temporary_failure.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/temporary_failure.php index 0ca8a48bc9e10..8f969745ba155 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/temporary_failure.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/temporary_failure.php @@ -6,7 +6,7 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521472262.908181)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521472262.908181')); $wh->setReason("4.2.2 The email account that you tried to reach is over quota. Please direct\n4.2.2 the recipient to\n4.2.2 https://support.example.com/mail/?p=422"); return $wh; diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/unsubscribes.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/unsubscribes.php index 1f38f2e9184ff..7261cbbc0e9b6 100644 --- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/unsubscribes.php +++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Tests/Webhook/Fixtures/unsubscribes.php @@ -6,6 +6,6 @@ $wh->setRecipientEmail('alice@example.com'); $wh->setTags(['my_tag_1', 'my_tag_2']); $wh->setMetadata(['my_var_1' => 'Mailgun Variable #1', 'my-var-2' => 'awesome']); -$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', 1521243339.873676)); +$wh->setDate(\DateTimeImmutable::createFromFormat('U.u', '1521243339.873676')); return $wh; From e32c833e04826c8e6c836595acd6a194242479c6 Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Fri, 1 Sep 2023 22:31:43 +0200 Subject: [PATCH 09/55] [DoctrineBridge][Security] Rename loadUserByUsername tests to loadUserByIdentifier --- .../Tests/Security/User/EntityUserProviderTest.php | 10 +++++----- .../Security/Core/Tests/User/ChainUserProviderTest.php | 4 ++-- .../Core/Tests/User/InMemoryUserProviderTest.php | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php index 7d068d4c56307..d0becddbc76f3 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/User/EntityUserProviderTest.php @@ -49,7 +49,7 @@ public function testRefreshUserGetsUserByPrimaryKey() $this->assertSame($user1, $provider->refreshUser($user1)); } - public function testLoadUserByUsername() + public function testLoadUserByIdentifier() { $em = DoctrineTestHelper::createTestEntityManager(); $this->createSchema($em); @@ -64,7 +64,7 @@ public function testLoadUserByUsername() $this->assertSame($user, $provider->loadUserByIdentifier('user1')); } - public function testLoadUserByUsernameWithUserLoaderRepositoryAndWithoutProperty() + public function testLoadUserByIdentifierWithUserLoaderRepositoryAndWithoutProperty() { $user = new User(1, 1, 'user1'); @@ -86,7 +86,7 @@ public function testLoadUserByUsernameWithUserLoaderRepositoryAndWithoutProperty $this->assertSame($user, $provider->loadUserByIdentifier('user1')); } - public function testLoadUserByUsernameWithNonUserLoaderRepositoryAndWithoutProperty() + public function testLoadUserByIdentifierWithNonUserLoaderRepositoryAndWithoutProperty() { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('You must either make the "Symfony\Bridge\Doctrine\Tests\Fixtures\User" entity Doctrine Repository ("Doctrine\ORM\EntityRepository") implement "Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface" or set the "property" option in the corresponding entity provider configuration.'); @@ -150,7 +150,7 @@ public function testSupportProxy() $this->assertTrue($provider->supportsClass($user2::class)); } - public function testLoadUserByUserNameShouldLoadUserWhenProperInterfaceProvided() + public function testLoadUserByIdentifierShouldLoadUserWhenProperInterfaceProvided() { $repository = $this->createMock(UserLoaderRepository::class); $repository->expects($this->once()) @@ -168,7 +168,7 @@ public function testLoadUserByUserNameShouldLoadUserWhenProperInterfaceProvided( $provider->loadUserByIdentifier('name'); } - public function testLoadUserByUserNameShouldDeclineInvalidInterface() + public function testLoadUserByIdentifierShouldDeclineInvalidInterface() { $this->expectException(\InvalidArgumentException::class); $repository = $this->createMock(ObjectRepository::class); diff --git a/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php b/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php index a5a74f0b05651..09227752bb0ee 100644 --- a/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php @@ -23,7 +23,7 @@ class ChainUserProviderTest extends TestCase { - public function testLoadUserByUsername() + public function testLoadUserByIdentifier() { $provider1 = $this->createMock(InMemoryUserProvider::class); $provider1 @@ -45,7 +45,7 @@ public function testLoadUserByUsername() $this->assertSame($account, $provider->loadUserByIdentifier('foo')); } - public function testLoadUserByUsernameThrowsUserNotFoundException() + public function testLoadUserByIdentifierThrowsUserNotFoundException() { $this->expectException(UserNotFoundException::class); $provider1 = $this->createMock(InMemoryUserProvider::class); diff --git a/src/Symfony/Component/Security/Core/Tests/User/InMemoryUserProviderTest.php b/src/Symfony/Component/Security/Core/Tests/User/InMemoryUserProviderTest.php index da0d832d846ab..1a843e4e71c55 100644 --- a/src/Symfony/Component/Security/Core/Tests/User/InMemoryUserProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/User/InMemoryUserProviderTest.php @@ -68,7 +68,7 @@ public function testCreateUserAlreadyExist() $provider->createUser(new InMemoryUser('fabien', 'foo')); } - public function testLoadUserByUsernameDoesNotExist() + public function testLoadUserByIdentifierDoesNotExist() { $this->expectException(UserNotFoundException::class); $provider = new InMemoryUserProvider(); From 2220955d08db800dd43fab4d6d5b3311a4a60104 Mon Sep 17 00:00:00 2001 From: Antoine Lamirault Date: Fri, 1 Sep 2023 22:45:38 +0200 Subject: [PATCH 10/55] [Security] alway use getUserIdentifier in InMemoryTokenProvider --- .../Core/Authentication/RememberMe/InMemoryTokenProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php b/src/Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php index 341883f3c548e..612870548cda4 100644 --- a/src/Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/RememberMe/InMemoryTokenProvider.php @@ -42,7 +42,7 @@ public function updateToken(string $series, #[\SensitiveParameter] string $token $token = new PersistentToken( $this->tokens[$series]->getClass(), - method_exists($this->tokens[$series], 'getUserIdentifier') ? $this->tokens[$series]->getUserIdentifier() : $this->tokens[$series]->getUsername(), + $this->tokens[$series]->getUserIdentifier(), $series, $tokenValue, $lastUsed From bfc4bddc7b9358dfb77dfa76446380b40a219290 Mon Sep 17 00:00:00 2001 From: Caligone Date: Sat, 2 Sep 2023 09:45:59 +0200 Subject: [PATCH 11/55] [Serializer] Looking for DiscriminatorMap on interfaces when the current object also extends from a class --- .../ClassDiscriminatorFromClassMetadata.php | 4 +++- .../Tests/Fixtures/DummyMessageInterface.php | 3 ++- .../Fixtures/DummyMessageNumberThree.php | 19 +++++++++++++++++++ .../Serializer/Tests/SerializerTest.php | 13 +++++++++++++ 4 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.php diff --git a/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php b/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php index 23554ffda98ab..6f69c890b91d9 100644 --- a/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php +++ b/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorFromClassMetadata.php @@ -78,7 +78,9 @@ private function resolveMappingForMappedObject($object) { $reflectionClass = new \ReflectionClass($object); if ($parentClass = $reflectionClass->getParentClass()) { - return $this->getMappingForMappedObject($parentClass->getName()); + if (null !== ($parentMapping = $this->getMappingForMappedObject($parentClass->getName()))) { + return $parentMapping; + } } foreach ($reflectionClass->getInterfaceNames() as $interfaceName) { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php index 55bb00bc8e253..78beb8374aaff 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageInterface.php @@ -16,7 +16,8 @@ /** * @DiscriminatorMap(typeProperty="type", mapping={ * "one"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne", - * "two"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo" + * "two"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo", + * "three"="Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberThree" * }) * * @author Samuel Roze diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.php b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.php new file mode 100644 index 0000000000000..e15fc62c7bae0 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/DummyMessageNumberThree.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +/** + * @author Samuel Roze + */ +class DummyMessageNumberThree extends \stdClass implements DummyMessageInterface +{ +} diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index b4e84132a0858..2141c0cf6d334 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -58,6 +58,7 @@ use Symfony\Component\Serializer\Tests\Fixtures\DummyFirstChildQuux; use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageInterface; use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberOne; +use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberThree; use Symfony\Component\Serializer\Tests\Fixtures\DummyMessageNumberTwo; use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumConstructor; use Symfony\Component\Serializer\Tests\Fixtures\DummyObjectWithEnumProperty; @@ -488,6 +489,18 @@ public function testDeserializeAndSerializeNestedInterfacedObjectsWithTheClassMe $this->assertEquals($example, $deserialized); } + public function testDeserializeAndSerializeNestedAbstractAndInterfacedObjectsWithTheClassMetadataDiscriminator() + { + $example = new DummyMessageNumberThree(); + + $serializer = $this->serializerWithClassDiscriminator(); + + $serialized = $serializer->serialize($example, 'json'); + $deserialized = $serializer->deserialize($serialized, DummyMessageInterface::class, 'json'); + + $this->assertEquals($example, $deserialized); + } + public function testExceptionWhenTypeIsNotKnownInDiscriminator() { try { From db70e6b8a9b96fbb49734a90bce879da4779c74e Mon Sep 17 00:00:00 2001 From: Marko Kaznovac Date: Mon, 4 Sep 2023 23:33:54 +0200 Subject: [PATCH 12/55] UrlHelper: minor code style fix --- src/Symfony/Component/HttpFoundation/UrlHelper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/UrlHelper.php b/src/Symfony/Component/HttpFoundation/UrlHelper.php index d5641eff86d58..f971cf66297b4 100644 --- a/src/Symfony/Component/HttpFoundation/UrlHelper.php +++ b/src/Symfony/Component/HttpFoundation/UrlHelper.php @@ -21,7 +21,6 @@ */ final class UrlHelper { - public function __construct( private RequestStack $requestStack, private RequestContextAwareInterface|RequestContext|null $requestContext = null, From 772050bbc58ad91f6357eb286f499d6a8069f870 Mon Sep 17 00:00:00 2001 From: kgnblg Date: Tue, 5 Sep 2023 16:43:46 +0200 Subject: [PATCH 13/55] bug [mailer] fix EsmtpTransport variable $code definition the variable $code defined in the foreach loop, if there is no authenticators, then the $code will not be defined and therefore the following TransportException gives a PHP error. the use-case defined as a unit test in EsmtpTransportTest class. --- .../Transport/Smtp/EsmtpTransportTest.php | 22 +++++++++++++++++++ .../Mailer/Transport/Smtp/EsmtpTransport.php | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php index 39dea5d3f3e62..8e7832258bd47 100644 --- a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php +++ b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/EsmtpTransportTest.php @@ -192,6 +192,28 @@ public function testSetAuthenticators() $stream->getCommands() ); } + + public function testConstructorWithEmptyAuthenticator() + { + $stream = new DummyStream(); + $transport = new EsmtpTransport(stream: $stream); + $transport->setUsername('testuser'); + $transport->setPassword('p4ssw0rd'); + $transport->setAuthenticators([]); // if no authenticators defined, then there needs to be a TransportException + + $message = new Email(); + $message->from('sender@example.org'); + $message->addTo('recipient@example.org'); + $message->text('.'); + + try { + $transport->send($message); + $this->fail('Symfony\Component\Mailer\Exception\TransportException to be thrown'); + } catch (TransportException $e) { + $this->assertStringStartsWith('Failed to find an authenticator supported by the SMTP server, which currently supports: "plain", "login", "cram-md5", "xoauth2".', $e->getMessage()); + $this->assertEquals(504, $e->getCode()); + } + } } class CustomEsmtpTransport extends EsmtpTransport diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php index 83aef862155bf..b903d61ab3218 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php @@ -184,6 +184,7 @@ private function handleAuth(array $modes): void return; } + $code = null; $authNames = []; $errors = []; $modes = array_map('strtolower', $modes); @@ -192,7 +193,6 @@ private function handleAuth(array $modes): void continue; } - $code = null; $authNames[] = $authenticator->getAuthKeyword(); try { $authenticator->authenticate($this); From ce4bc8c447d8816d40e332c6aaaa0138c22afffb Mon Sep 17 00:00:00 2001 From: kgnblg Date: Wed, 6 Sep 2023 11:47:15 +0200 Subject: [PATCH 14/55] [mailer] reset $code variable each iteration for prevent wrong codes to be used --- src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php index b903d61ab3218..2683050c9cb22 100644 --- a/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php +++ b/src/Symfony/Component/Mailer/Transport/Smtp/EsmtpTransport.php @@ -193,6 +193,7 @@ private function handleAuth(array $modes): void continue; } + $code = null; $authNames[] = $authenticator->getAuthKeyword(); try { $authenticator->authenticate($this); From 809cf7403771d123134139819e6508466a8258d2 Mon Sep 17 00:00:00 2001 From: "Phil E. Taylor" Date: Wed, 6 Sep 2023 22:45:09 +0100 Subject: [PATCH 15/55] PHP 8.3 highlight_file function output changes --- .../Bridge/Twig/Extension/CodeExtension.php | 26 ++++++++++++++----- .../ErrorRenderer/HtmlErrorRenderer.php | 26 ++++++++++++++----- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 3bf8ccd294b41..59845396cfe40 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -123,13 +123,25 @@ public function fileExcerpt(string $file, int $line, int $srcContext = 3): ?stri // highlight_file could throw warnings // see https://bugs.php.net/25725 $code = @highlight_file($file, true); - // remove main code/span tags - $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { - return "".str_replace('
', "

", $m[2]).''; - }, $code); - $content = explode('
', $code); + if (\PHP_VERSION_ID >= 80300) { + // remove main pre/code tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline code tags + $code = preg_replace_callback('#]++)>((?:[^<]*+\\n)++[^<]*+)#', function ($m) { + return "".str_replace("\n", "\n", $m[2]).''; + }, $code); + // Convert spaces to html entities to preserve indentation when rendered + $code = str_replace(' ', ' ', $code); + $content = explode("\n", $code); + } else { + // remove main code/span tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline spans + $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { + return "".str_replace('
', "

", $m[2]).''; + }, $code); + $content = explode('
', $code); + } $lines = []; if (0 > $srcContext) { diff --git a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php index b8a9aeda61fda..92434b8e94506 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php +++ b/src/Symfony/Component/ErrorHandler/ErrorRenderer/HtmlErrorRenderer.php @@ -269,13 +269,25 @@ private function fileExcerpt(string $file, int $line, int $srcContext = 3): stri // highlight_file could throw warnings // see https://bugs.php.net/25725 $code = @highlight_file($file, true); - // remove main code/span tags - $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { - return "".str_replace('
', "

", $m[2]).''; - }, $code); - $content = explode('
', $code); + if (\PHP_VERSION_ID >= 80300) { + // remove main pre/code tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline code tags + $code = preg_replace_callback('#]++)>((?:[^<]*+\\n)++[^<]*+)#', function ($m) { + return "".str_replace("\n", "\n", $m[2]).''; + }, $code); + // Convert spaces to html entities to preserve indentation when rendered + $code = str_replace(' ', ' ', $code); + $content = explode("\n", $code); + } else { + // remove main code/span tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline spans + $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', function ($m) { + return "".str_replace('
', "

", $m[2]).''; + }, $code); + $content = explode('
', $code); + } $lines = []; if (0 > $srcContext) { From e1a14b754b0333b719a078c58c88103ac46789b0 Mon Sep 17 00:00:00 2001 From: HypeMC Date: Thu, 7 Sep 2023 00:39:36 +0200 Subject: [PATCH 16/55] [FrameworkBundle] Always use buildDir as `ConfigBuilderGenerator` outputDir --- .../CacheWarmer/ConfigBuilderCacheWarmer.php | 2 +- .../ConfigBuilderCacheWarmerTest.php | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php index ed20bbcb648d7..50843f5263c18 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ConfigBuilderCacheWarmer.php @@ -44,7 +44,7 @@ public function __construct(KernelInterface $kernel, LoggerInterface $logger = n */ public function warmUp(string $cacheDir) { - $generator = new ConfigBuilderGenerator($cacheDir); + $generator = new ConfigBuilderGenerator($this->kernel->getBuildDir()); foreach ($this->kernel->getBundles() as $bundle) { $extension = $bundle->getContainerExtension(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php new file mode 100644 index 0000000000000..c64e5d3b4cdd3 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ConfigBuilderCacheWarmerTest.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer; + +use Symfony\Bundle\FrameworkBundle\CacheWarmer\ConfigBuilderCacheWarmer; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\TestCase; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\HttpKernel\Kernel; + +class ConfigBuilderCacheWarmerTest extends TestCase +{ + private $varDir; + + protected function setUp(): void + { + $this->varDir = sys_get_temp_dir().'/'.uniqid(); + $fs = new Filesystem(); + $fs->mkdir($this->varDir); + } + + protected function tearDown(): void + { + $fs = new Filesystem(); + $fs->remove($this->varDir); + unset($this->varDir); + } + + public function testBuildDirIsUsedAsConfigBuilderOutputDir() + { + $kernel = new class($this->varDir) extends Kernel { + private $varDir; + + public function __construct(string $varDir) + { + parent::__construct('test', false); + + $this->varDir = $varDir; + } + + public function registerBundles(): iterable + { + yield new FrameworkBundle(); + } + + public function getBuildDir(): string + { + return $this->varDir.'/build'; + } + + public function getCacheDir(): string + { + return $this->varDir.'/cache'; + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + } + }; + $kernel->boot(); + + $warmer = new ConfigBuilderCacheWarmer($kernel); + $warmer->warmUp($kernel->getCacheDir()); + + self::assertDirectoryExists($kernel->getBuildDir().'/Symfony'); + self::assertDirectoryDoesNotExist($kernel->getCacheDir().'/Symfony'); + } +} From 9dafdc1e4a1d5fa875d8ed7f888c43be3fd3cc1f Mon Sep 17 00:00:00 2001 From: "d.huethorst" Date: Tue, 27 Jun 2023 12:23:58 +0200 Subject: [PATCH 17/55] [TwigBridge] Change return type of Symfony\Bridge\Twig\AppVariable::getSession() --- src/Symfony/Bridge/Twig/AppVariable.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/AppVariable.php b/src/Symfony/Bridge/Twig/AppVariable.php index 8bfaa0a22c601..abcbff9255ad5 100644 --- a/src/Symfony/Bridge/Twig/AppVariable.php +++ b/src/Symfony/Bridge/Twig/AppVariable.php @@ -13,7 +13,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; @@ -112,7 +112,7 @@ public function getRequest(): ?Request /** * Returns the current session. */ - public function getSession(): ?Session + public function getSession(): ?SessionInterface { if (!isset($this->requestStack)) { throw new \RuntimeException('The "app.session" variable is not available.'); @@ -171,6 +171,12 @@ public function getFlashes(string|array $types = null): array return []; } + // In 7.0 (when symfony/http-foundation: 6.4 is required) this can be updated to + // check if the session is an instance of FlashBagAwareSessionInterface + if (!method_exists($session, 'getFlashBag')) { + return []; + } + if (null === $types || '' === $types || [] === $types) { return $session->getFlashBag()->all(); } From 0182fc7d306cd4253dc1550946686d2cbee0c14e Mon Sep 17 00:00:00 2001 From: Makrevski Zoran Date: Sat, 9 Sep 2023 10:37:18 +0300 Subject: [PATCH 18/55] [Form][Security][Validator] Add mk translations --- .../Resources/translations/validators.mk.xlf | 139 ++++++ .../Resources/translations/security.mk.xlf | 83 ++++ .../Resources/translations/validators.mk.xlf | 431 ++++++++++++++++++ 3 files changed, 653 insertions(+) create mode 100644 src/Symfony/Component/Form/Resources/translations/validators.mk.xlf create mode 100644 src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf create mode 100644 src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf diff --git a/src/Symfony/Component/Form/Resources/translations/validators.mk.xlf b/src/Symfony/Component/Form/Resources/translations/validators.mk.xlf new file mode 100644 index 0000000000000..ea86b304cee25 --- /dev/null +++ b/src/Symfony/Component/Form/Resources/translations/validators.mk.xlf @@ -0,0 +1,139 @@ + + + + + + This form should not contain extra fields. + Оваа форма не треба да содржи дополнителни полиња. + + + The uploaded file was too large. Please try to upload a smaller file. + Датотеката што се обидовте да ја подигнете е преголема. Ве молиме обидете се со помала датотека. + + + The CSRF token is invalid. Please try to resubmit the form. + Вашиот CSRF токен е невалиден. Ве молиме испратете ја формата одново. + + + This value is not a valid HTML5 color. + Оваа вредност не е валидна HTML5 боја. + + + Please enter a valid birthdate. + Ве молиме внесете валидна дата на раѓање. + + + The selected choice is invalid. + Избраната опција е невалидна. + + + The collection is invalid. + Колекцијата е невалидна. + + + Please select a valid color. + Ве молиме одберете валидна боја. + + + Please select a valid country. + Ве молиме одберете валидна земја. + + + Please select a valid currency. + Ве молиме одберете валидна валута. + + + Please choose a valid date interval. + Ве молиме одберете валиден интервал помеѓу два датума. + + + Please enter a valid date and time. + Ве молиме внесете валиден датум и време. + + + Please enter a valid date. + Ве молиме внесете валиден датум. + + + Please select a valid file. + Ве молиме одберете валидна датотека. + + + The hidden field is invalid. + Скриеното поле е невалидно. + + + Please enter an integer. + Ве молиме внесете цел број. + + + Please select a valid language. + Ве молиме одберете валиден јазик. + + + Please select a valid locale. + Ве молиме одберете валидна локализација. + + + Please enter a valid money amount. + Ве молиме внесете валидна сума на пари. + + + Please enter a number. + Ве молиме внесете број. + + + The password is invalid. + Лозинката е погрешна. + + + Please enter a percentage value. + Ве молиме внесете процентуална вредност. + + + The values do not match. + Вредностите не се совпаѓаат. + + + Please enter a valid time. + Ве молиме внесете валидно време. + + + Please select a valid timezone. + Ве молиме одберете валидна временска зона. + + + Please enter a valid URL. + Ве молиме внесете валиден униформен локатор на ресурси (URL). + + + Please enter a valid search term. + Ве молиме внесете валиден термин за пребарување. + + + Please provide a valid phone number. + Ве молиме внесете валиден телефонски број. + + + The checkbox has an invalid value. + Полето за штиклирање има неважечка вредност. + + + Please enter a valid email address. + Ве молиме внесете валидна адреса за е-пошта. + + + Please select a valid option. + Ве молиме одберете валидна опција. + + + Please select a valid range. + Ве молиме одберете важечки опсег. + + + Please enter a valid week. + Ве молиме внесете валидна недела. + + + + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf new file mode 100644 index 0000000000000..051affcf8b241 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.mk.xlf @@ -0,0 +1,83 @@ + + + + + + An authentication exception occurred. + Настана грешка во автентикацијата. + + + Authentication credentials could not be found. + Акредитивите за автентикација не се пронајдени. + + + Authentication request could not be processed due to a system problem. + Барањето за автентикација не можеше да биде процесуирано заради системски проблем. + + + Invalid credentials. + Невалидни акредитиви. + + + Cookie has already been used by someone else. + Колачето е веќе користено од некој друг. + + + Not privileged to request the resource. + Немате привилегии за да го побарате ресурсот. + + + Invalid CSRF token. + Невалиден CSRF токен. + + + No authentication provider found to support the authentication token. + Не е пронајден провајдер за автентикација кој го поддржува токенот за автентикација. + + + No session available, it either timed out or cookies are not enabled. + Сесијата е недостапна, или е истечена, или колачињата не се овозможени. + + + No token could be found. + Токенот не е најден. + + + Username could not be found. + Корисничкото име не е најдено. + + + Account has expired. + Корисничката сметка е истечена. + + + Credentials have expired. + Акредитивите се истечени. + + + Account is disabled. + Корисничката сметка е деактивирана. + + + Account is locked. + Корисничката сметка е заклучена. + + + Too many failed login attempts, please try again later. + Премногу неуспешни обиди за најавување, ве молиме обидете се повторно подоцна. + + + Invalid or expired login link. + Неважечка или истечена врска за најавување. + + + Too many failed login attempts, please try again in %minutes% minute. + Премногу неуспешни обиди за најавување, обидете се повторно за %minutes% минута. + + + Too many failed login attempts, please try again in %minutes% minutes. + Премногу неуспешни обиди за најавување, обидете се повторно за %minutes% минути. + + + + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf new file mode 100644 index 0000000000000..eb15989839b8a --- /dev/null +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mk.xlf @@ -0,0 +1,431 @@ + + + + + + This value should be false. + Оваа вредност треба да биде лажна. + + + This value should be true. + Оваа вредност треба да биде вистинита. + + + This value should be of type {{ type }}. + Оваа вредност треба да биде од типот {{ type }}. + + + This value should be blank. + Оваа вредност треба да биде празна. + + + The value you selected is not a valid choice. + Вредноста што ја одбравте не е валиден избор. + + + You must select at least {{ limit }} choice.|You must select at least {{ limit }} choices. + Мора да одберете најмалку {{ limit }} избор.|Мора да одберете најмалку {{ limit }} изброи. + + + You must select at most {{ limit }} choice.|You must select at most {{ limit }} choices. + Може да одберете најмногу {{ limit }} избор.|Мора да одберете најмногу {{ limit }} избори. + + + One or more of the given values is invalid. + Една или повеќе од дадените вредности не се валидни. + + + This field was not expected. + Ова поле не беше очекувано. + + + This field is missing. + Ова поле недостига. + + + This value is not a valid date. + Оваа вредност не е валиден датум. + + + This value is not a valid datetime. + Оваа вредност не е валиден датум и време. + + + This value is not a valid email address. + Оваа вредност не е валидна адреса за е-пошта. + + + The file could not be found. + Датотеката не е најдена. + + + The file is not readable. + Датотеката не може да биде прочитана. + + + The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. + Датотеката е премногу голема ({{ size }} {{ suffix }}). Максималната дозволена големина е {{ limit }} {{ suffix }}. + + + The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. + Миме типот на датотеката не е валиден ({{ type }}). Дозволените миме типови се {{ types }}. + + + This value should be {{ limit }} or less. + Оваа вредност треба да биде {{ limit }} или помалку. + + + This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. + Оваа вредност е предолга. Треба да содржи {{ limit }} карактер или помалку.|Оваа вредност е предолга. Треба да содржи {{ limit }} карактери или помалку. + + + This value should be {{ limit }} or more. + Оваа вредност треба да е {{ limit }} или повеќе. + + + This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. + Оваа вредност е прекратка. Треба да содржи {{ limit }} карактер или повеќе.|Оваа вредност е прекратка. Треба да содржи {{ limit }} карактери или повеќе. + + + This value should not be blank. + Ова поле не може да биде празно. + + + This value should not be null. + Оваа вредност не може да биде ништо (null). + + + This value should be null. + Оваа вредност треба да е ништо (null). + + + This value is not valid. + Оваа вредност не е валидна. + + + This value is not a valid time. + Оваа вредност не е валидно време. + + + This value is not a valid URL. + Оваа вредност не е валиден URL. + + + The two values should be equal. + Двете вредности треба да се еднакви. + + + The file is too large. Allowed maximum size is {{ limit }} {{ suffix }}. + Датотеката е премногу голема. Максималната дозволена големина е {{ limit }} {{ suffix }}. + + + The file is too large. + Датотеката е премногу голема. + + + The file could not be uploaded. + Датотеката не може да биде подигната. + + + This value should be a valid number. + Оваа вредност треба да е валиден број. + + + This file is not a valid image. + Оваа датотека не е валидна слика. + + + This is not a valid IP address. + Ова не е валидна IP адреса. + + + This value is not a valid language. + Оваа вредност не е валиден јазик. + + + This value is not a valid locale. + Оваа вредност не е валидна локализација. + + + This value is not a valid country. + Оваа вредност не е валидна земја. + + + This value is already used. + Оваа вредност веќе се користи. + + + The size of the image could not be detected. + Големината на сликата не може да се детектира. + + + The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. + Ширината на сликата е преголема ({{ width }}px). Максималната дозволена ширина е {{ max_width }}px. + + + The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. + Ширината на сликата е премала ({{ width }}px). Минималната дозволена ширина е {{ min_width }}px. + + + The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. + Висината на сликата е преголема ({{ height }}px). Максималната дозволена висина е {{ max_height }}px. + + + The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. + Висината на сликата е премала ({{ height }}px). Минималната дозволена висина е {{ min_height }}px. + + + This value should be the user's current password. + Оваа вредност треба да биде сегашната лозинка на корисникот. + + + This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. + Оваа вредност треба да има точно {{ limit }} карактер.|Оваа вредност треба да има точно {{ limit }} карактери. + + + The file was only partially uploaded. + Датотеката е само делумно подигната. + + + No file was uploaded. + Датотеката не е подигната. + + + No temporary folder was configured in php.ini. + Ниту една привремена папка не е конфигурирана во php.ini. + + + Cannot write temporary file to disk. + Не може да се напише привремена датотека на дискот. + + + A PHP extension caused the upload to fail. + PHP екстензијата предизвика подигнувањето да биде неуспешно. + + + This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. + Оваа колекција треба да содржи {{ limit }} елемент или повеќе.|Оваа колекција треба да содржи {{ limit }} елементи или повеќе. + + + This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. + Оваа колекција треба да содржи {{ limit }} елемент или помалку.|Оваа колекција треба да содржи {{ limit }} елементи или помалку. + + + This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. + Оваа колекција треба да содржи точно {{ limit }} елемент.|Оваа колекција треба да содржи точно {{ limit }} елементи. + + + Invalid card number. + Бројот на картичката не е валиден. + + + Unsupported card type or invalid card number. + Неподдржан тип на картичка или бројот на картичката не е валиден. + + + This is not a valid International Bank Account Number (IBAN). + Ова не е валиден број на меѓународна банкарска сметка (IBAN). + + + This value is not a valid ISBN-10. + Оваа вредност не е валиден ISBN-10. + + + This value is not a valid ISBN-13. + Оваа вредност не е валиден ISBN-13. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Оваа вредност не е ниту валиден ISBN-10 ниту валиден ISBN-13. + + + This value is not a valid ISSN. + Оваа вредност не е валиден ISSN. + + + This value is not a valid currency. + Оваа вредност не е валидна валута. + + + This value should be equal to {{ compared_value }}. + Оваа вредност треба да биде еднаква на {{ compared_value }}. + + + This value should be greater than {{ compared_value }}. + Оваа вредност треба да е поголема од {{ compared_value }}. + + + This value should be greater than or equal to {{ compared_value }}. + Оваа вредност треба да е поголема или еднаква на {{ compared_value }}. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Оваа вредност треба да е идентична на {{ compared_value_type }} {{ compared_value }}. + + + This value should be less than {{ compared_value }}. + Оваа вредност треба да е помала од {{ compared_value }}. + + + This value should be less than or equal to {{ compared_value }}. + Оваа вредност треба да е помала или еднаква на {{ compared_value }}. + + + This value should not be equal to {{ compared_value }}. + Оваа вредност треба да не биде еднаква на {{ compared_value }}. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Оваа вредност треба да не биде идентична со {{ compared_value_type }} {{ compared_value }}. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Соодносот на сликата е преголем ({{ ratio }}).Максималниот дозволен сооднос е {{ max_ratio }}. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Соодносот на сликата е премал ({{ ratio }}). Минималниот дозволен сооднос е {{ min_ratio }}. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Сликата е квадратна ({{ width }}x{{ height }}px). Квадратни слики не се дозволени. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Сликата е ориентирана кон пејзаж ({{ width }}x{{ height }}px). Сликите ориентирани кон пејзаж не се дозволени. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Сликата е ориентирана кон портрет ({{ width }}x{{ height }}px). Сликите ориентирани кон портрет не се дозволени. + + + An empty file is not allowed. + Празна датотека не е дозволена. + + + The host could not be resolved. + Хостот е недостапен. + + + This value does not match the expected {{ charset }} charset. + Оваа вредност не се совпаѓа со очекуваниот {{ charset }} сет на карактери (charset). + + + This is not a valid Business Identifier Code (BIC). + Ова не е валиден бизнис идентификациски код (BIC). + + + Error + Грешка + + + This is not a valid UUID. + Ова не е валиден универзален уникатен идентификатор (UUID). + + + This value should be a multiple of {{ compared_value }}. + Оваа вредност треба да биде повеќекратна од {{ compared_value }}. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Овој бизнис идентификациски код (BIC) не е поврзан со IBAN {{ iban }}. + + + This value should be valid JSON. + Оваа вредност треба да биде валиден JSON. + + + This collection should contain only unique elements. + Оваа колекција треба да содржи само уникатни елементи. + + + This value should be positive. + Оваа вредност треба да биде позитивна. + + + This value should be either positive or zero. + Оваа вредност треба да биде или позитивна или нула. + + + This value should be negative. + Оваа вредност треба да биде негативна. + + + This value should be either negative or zero. + Оваа вредност треба да биде или негативна или нула. + + + This value is not a valid timezone. + Оваа вредност не е валидна временска зона. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + Оваа лозинка е компромитирана и не смее да биде користена. Ве молиме употребете друга лозинка. + + + This value should be between {{ min }} and {{ max }}. + Оваа вредност треба да е помеѓу {{ min }} и {{ max }}. + + + This value is not a valid hostname. + Оваа вредност не е валидно име за мрежниот сметач (hostname). + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Бројот на елементи во оваа колекција треба да биде повеќекратен од {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Оваа вредност треба да задоволува најмалку едно од следните ограничувања: + + + Each element of this collection should satisfy its own set of constraints. + Секој елемент од оваа колекција треба да задоволува сопствен сет на ограничувања. + + + This value is not a valid International Securities Identification Number (ISIN). + Оваа вредност не е важечки меѓународен идентификациски број за хартии од вредност (ISIN). + + + This value should be a valid expression. + Оваа вредност треба да биде валиден израз. + + + This value is not a valid CSS color. + Оваа вредност не е валидна CSS боја. + + + This value is not a valid CIDR notation. + Оваа вредност не е валидна CIDR ознака. + + + The value of the netmask should be between {{ min }} and {{ max }}. + Вредноста на мрежната маска (netmask) треба да биде помеѓу {{ min }} и {{ max }}. + + + The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. + Името на датотеката е предолго. Треба да има {{ filename_max_length }} карактер има помалку.|Името на датотеката е предолго. Треба да има {{ filename_max_length }} карактери или помалку. + + + The password strength is too low. Please use a stronger password. + Оваа лозинка е премногу едноставна. Ве молиме користете посилна лозинка. + + + This value contains characters that are not allowed by the current restriction-level. + Оваа вредност содржи карактери кои не се дозволени од тековното ниво на ограничување. + + + Using invisible characters is not allowed. + Користењето на невидливи знаци не е дозволено. + + + Mixing numbers from different scripts is not allowed. + Не е дозволено мешање на броеви од различни скрипти. + + + Using hidden overlay characters is not allowed. + Не е дозволено користење на скриени знаци за преклопување. + + + + From 578a15200b33c21d161b40261b0a8ef74119008c Mon Sep 17 00:00:00 2001 From: Markus Fasselt Date: Thu, 7 Sep 2023 21:58:43 +0200 Subject: [PATCH 19/55] [Cache] fix using multiple Redis Sentinel hosts when the first one is not resolvable --- src/Symfony/Component/Cache/Traits/RedisTrait.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 220e65e744d43..0e7740e628369 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -217,8 +217,11 @@ public static function createConnection(string $dsn, array $options = []) } $sentinel = new \RedisSentinel($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra); - if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { - [$host, $port] = $address; + try { + if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { + [$host, $port] = $address; + } + } catch (\RedisException $e) { } } while (++$hostIndex < \count($hosts) && !$address); From 26cff6cc1dcbeba4fa0e16c8167a15d24bf37f5e Mon Sep 17 00:00:00 2001 From: Uladzimir Tsykun Date: Mon, 11 Sep 2023 15:00:41 +0200 Subject: [PATCH 20/55] Fix security tests --- src/Symfony/Bundle/SecurityBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index b2706f3e5256f..11ad25cdb303b 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -29,7 +29,7 @@ "symfony/password-hasher": "^5.4|^6.0", "symfony/security-core": "^6.2", "symfony/security-csrf": "^5.4|^6.0", - "symfony/security-http": "^6.3" + "symfony/security-http": "^6.3.4" }, "require-dev": { "doctrine/annotations": "^1.10.4|^2", From c557647ede0bae07098067bb25c2eaaf49277a5b Mon Sep 17 00:00:00 2001 From: Uladzimir Tsykun Date: Mon, 11 Sep 2023 18:39:34 +0200 Subject: [PATCH 21/55] Make tests green again --- .../Component/VarDumper/Tests/Dumper/CliDumperTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index 7809fcdb9f523..1c7dcc07ff4e9 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -553,6 +553,10 @@ public function testDumpArrayWithColor($value, $flags, $expectedOut) public function testCollapse() { + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->markTestSkipped('This test cannot be run on Windows.'); + } + $stub = new Stub(); $stub->type = Stub::TYPE_OBJECT; $stub->class = 'stdClass'; From 338e2da2d2e57cbbafac2d68713e529bce918572 Mon Sep 17 00:00:00 2001 From: Christopher Georg Date: Tue, 12 Sep 2023 09:44:46 +0200 Subject: [PATCH 22/55] chore: fix ci deprecations --- .github/workflows/integration-tests.yml | 4 ++-- .github/workflows/intl-data-tests.yml | 2 +- .github/workflows/package-tests.yml | 2 +- .github/workflows/phpunit-bridge.yml | 2 +- .github/workflows/psalm.yml | 4 ++-- .github/workflows/unit-tests.yml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index dc80c6fb28ce6..6e785c383a0f1 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -107,7 +107,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install system dependencies run: | @@ -191,7 +191,7 @@ jobs: # sudo rm -rf .phpunit # [ -d .phpunit.bak ] && mv .phpunit.bak .phpunit - - uses: marceloprado/has-changed-path@v1 + - uses: marceloprado/has-changed-path@v1.0.1 id: changed-translation-files with: paths: src/**/Resources/translations/*.xlf diff --git a/.github/workflows/intl-data-tests.yml b/.github/workflows/intl-data-tests.yml index 8db09e52912af..ac2b8d41237ad 100644 --- a/.github/workflows/intl-data-tests.yml +++ b/.github/workflows/intl-data-tests.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install system dependencies run: | diff --git a/.github/workflows/package-tests.yml b/.github/workflows/package-tests.yml index a6955dbead472..1840d30f091a6 100644 --- a/.github/workflows/package-tests.yml +++ b/.github/workflows/package-tests.yml @@ -14,7 +14,7 @@ jobs: runs-on: Ubuntu-20.04 steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Fetch branch from where the PR started run: git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/* diff --git a/.github/workflows/phpunit-bridge.yml b/.github/workflows/phpunit-bridge.yml index 2229bbc866655..f63c02bc31925 100644 --- a/.github/workflows/phpunit-bridge.yml +++ b/.github/workflows/phpunit-bridge.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index 219b8677325d0..27b51d5af7428 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -30,12 +30,12 @@ jobs: coverage: none - name: Checkout target branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.base_ref }} - name: Checkout PR - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install dependencies run: | diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 199887754e036..94b69e6c9891c 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -40,7 +40,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 2 From 4312e96c28eec5ba8825d71f8b751aa4e37f7df5 Mon Sep 17 00:00:00 2001 From: soyuka Date: Sun, 27 Aug 2023 12:21:37 +0200 Subject: [PATCH 23/55] [FrameworkBundle] no serializer mapping cache in debug mode without enable_annotations There's no reason we should disable the cache only without `enable_annotations`, when working only with attributes, in debug mode the cache is enabled which is why we often need to clear cache when changing a serialized object to get the changes. --- .../DependencyInjection/FrameworkExtension.php | 7 ++++--- .../DependencyInjection/FrameworkExtensionTestCase.php | 6 ++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 206bda1039a44..da60eeabb41c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1790,14 +1790,15 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->removeDefinition('serializer.normalizer.mime_message'); } + if ($container->getParameter('kernel.debug')) { + $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); + } + $serializerLoaders = []; if (isset($config['enable_annotations']) && $config['enable_annotations']) { if (\PHP_VERSION_ID < 80000 && !$this->annotationsConfigEnabled) { throw new \LogicException('"enable_annotations" on the serializer cannot be set as the PHP version is lower than 8 and Annotations support is disabled. Consider upgrading PHP.'); } - if ($container->getParameter('kernel.debug')) { - $container->removeDefinition('serializer.mapping.cache_class_metadata_factory'); - } $annotationLoader = new Definition( 'Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php index d1a0f52eac4fb..f5429d617b1a7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php @@ -1530,6 +1530,12 @@ public function testSerializerCacheActivated() public function testSerializerCacheUsedWithoutAnnotationsAndMappingFiles() { $container = $this->createContainerFromFile('serializer_mapping_without_annotations', ['kernel.debug' => true, 'kernel.container_class' => __CLASS__]); + $this->assertFalse($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); + } + + public function testSerializerCacheUsedWithoutAnnotationsAndMappingFilesNoDebug() + { + $container = $this->createContainerFromFile('serializer_mapping_without_annotations', ['kernel.debug' => false, 'kernel.container_class' => __CLASS__]); $this->assertTrue($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); } From 4264558fea9705c22c14fce0374db49efe665a09 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 13 Sep 2023 13:47:37 +0200 Subject: [PATCH 24/55] [String] Update wcswidth data with Unicode 15.1 --- .../String/Resources/WcswidthDataGenerator.php | 2 +- .../Resources/data/wcswidth_table_wide.php | 18 +++++++++++++++--- .../Resources/data/wcswidth_table_zero.php | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php b/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php index 69d32e292a990..7443d051ee14d 100644 --- a/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php +++ b/src/Symfony/Component/String/Resources/WcswidthDataGenerator.php @@ -46,7 +46,7 @@ private function writeWideWidthData(): void $version = $matches[1]; - if (!preg_match_all('/^([A-H\d]{4,})(?:\.\.([A-H\d]{4,}))?;[W|F]/m', $content, $matches, \PREG_SET_ORDER)) { + if (!preg_match_all('/^([A-H\d]{4,})(?:\.\.([A-H\d]{4,}))? +; [W|F]/m', $content, $matches, \PREG_SET_ORDER)) { throw new RuntimeException('The wide width pattern did not match anything.'); } diff --git a/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php b/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php index 5a647e67bf30f..8314c8fd504c2 100644 --- a/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php +++ b/src/Symfony/Component/String/Resources/data/wcswidth_table_wide.php @@ -3,8 +3,8 @@ /* * This file has been auto-generated by the Symfony String Component for internal use. * - * Unicode version: 15.0.0 - * Date: 2022-10-05T17:16:36+02:00 + * Unicode version: 15.1.0 + * Date: 2023-09-13T11:47:12+00:00 */ return [ @@ -166,7 +166,7 @@ ], [ 12272, - 12283, + 12287, ], [ 12288, @@ -396,6 +396,10 @@ 12736, 12771, ], + [ + 12783, + 12783, + ], [ 12784, 12799, @@ -1110,6 +1114,14 @@ ], [ 191457, + 191471, + ], + [ + 191472, + 192093, + ], + [ + 192094, 194559, ], [ diff --git a/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php b/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php index 9ae7330325291..e5b26a21515ea 100644 --- a/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php +++ b/src/Symfony/Component/String/Resources/data/wcswidth_table_zero.php @@ -3,8 +3,8 @@ /* * This file has been auto-generated by the Symfony String Component for internal use. * - * Unicode version: 15.0.0 - * Date: 2022-10-05T17:16:37+02:00 + * Unicode version: 15.1.0 + * Date: 2023-09-13T11:47:13+00:00 */ return [ From fdef0abb6e098430320cad11e86ee6f9d569a5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20H=C3=A9lias?= Date: Thu, 14 Sep 2023 22:49:15 +0200 Subject: [PATCH 25/55] [HttpClient] Fix TraceableResponse if response has no destruct method --- .../Component/HttpClient/Response/TraceableResponse.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php index d656c0a5f94d7..3bf1571fda1fb 100644 --- a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php +++ b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php @@ -57,7 +57,9 @@ public function __wakeup() public function __destruct() { try { - $this->response->__destruct(); + if (method_exists($this->response, '__destruct')) { + $this->response->__destruct(); + } } finally { if ($this->event && $this->event->isStarted()) { $this->event->stop(); From ff45ca11559380922240d3dc59b10740adfdd8d9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 15 Sep 2023 08:53:42 +0200 Subject: [PATCH 26/55] [Scheduler] Speed up tests --- src/Symfony/Component/Scheduler/Tests/SchedulerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Scheduler/Tests/SchedulerTest.php b/src/Symfony/Component/Scheduler/Tests/SchedulerTest.php index 770911b54791a..5031e4c405710 100644 --- a/src/Symfony/Component/Scheduler/Tests/SchedulerTest.php +++ b/src/Symfony/Component/Scheduler/Tests/SchedulerTest.php @@ -28,7 +28,7 @@ public function testCanRunAndStop() $scheduler = new Scheduler([Message::class => $handler], [$schedule], $clock); $handler->scheduler = $scheduler; - $scheduler->run(['sleep' => 1]); + $scheduler->run(['sleep' => 100]); $this->assertSame(3, $handler->count); } From 71cf59c994d5926728883485d18e6c92a9edeb1c Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 15 Sep 2023 15:46:46 +0200 Subject: [PATCH 27/55] [FrameworkBundle] Handle tags array attributes in descriptors --- .../Console/Descriptor/MarkdownDescriptor.php | 2 +- .../Console/Descriptor/TextDescriptor.php | 12 ++++- .../Console/Descriptor/ObjectsProvider.php | 1 + .../Descriptor/alias_with_definition_2.json | 18 ++++++++ .../Descriptor/alias_with_definition_2.md | 2 + .../Descriptor/alias_with_definition_2.txt | 44 ++++++++++--------- .../Descriptor/alias_with_definition_2.xml | 3 ++ .../Descriptor/builder_1_services.json | 18 ++++++++ .../Fixtures/Descriptor/builder_1_services.md | 2 + .../Descriptor/builder_1_services.xml | 3 ++ .../Fixtures/Descriptor/builder_1_tag1.json | 18 ++++++++ .../Fixtures/Descriptor/builder_1_tag1.md | 2 + .../Fixtures/Descriptor/builder_1_tag1.xml | 3 ++ .../Fixtures/Descriptor/builder_1_tags.json | 20 +++++++++ .../Fixtures/Descriptor/builder_1_tags.md | 21 +++++++++ .../Fixtures/Descriptor/builder_1_tags.txt | 5 +++ .../Fixtures/Descriptor/builder_1_tags.xml | 8 ++++ .../Fixtures/Descriptor/definition_2.json | 18 ++++++++ .../Tests/Fixtures/Descriptor/definition_2.md | 2 + .../Fixtures/Descriptor/definition_2.txt | 43 +++++++++--------- .../Fixtures/Descriptor/definition_2.xml | 3 ++ .../Descriptor/definition_arguments_2.json | 18 ++++++++ .../Descriptor/definition_arguments_2.md | 2 + .../Descriptor/definition_arguments_2.txt | 43 +++++++++--------- .../Descriptor/definition_arguments_2.xml | 3 ++ 25 files changed, 248 insertions(+), 66 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index 7423a28550c90..42574a80a57e9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -254,7 +254,7 @@ protected function describeContainerDefinition(Definition $definition, array $op foreach ($tagData as $parameters) { $output .= "\n".'- Tag: `'.$tagName.'`'; foreach ($parameters as $name => $value) { - $output .= "\n".' - '.ucfirst($name).': '.$value; + $output .= "\n".' - '.ucfirst($name).': '.(\is_array($value) ? $this->formatParameter($value) : $value); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 06afc5ceacdc9..444f3b512d43f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -209,6 +209,10 @@ protected function describeContainerServices(ContainerBuilder $container, array if (!isset($maxTags[$key])) { $maxTags[$key] = \strlen($key); } + if (\is_array($value)) { + $value = $this->formatParameter($value); + } + if (\strlen($value) > $maxTags[$key]) { $maxTags[$key] = \strlen($value); } @@ -233,7 +237,11 @@ protected function describeContainerServices(ContainerBuilder $container, array foreach ($this->sortByPriority($definition->getTag($showTag)) as $key => $tag) { $tagValues = []; foreach ($tagsNames as $tagName) { - $tagValues[] = $tag[$tagName] ?? ''; + if (\is_array($tagValue = $tag[$tagName] ?? '')) { + $tagValue = $this->formatParameter($tagValue); + } + + $tagValues[] = $tagValue; } if (0 === $key) { $tableRows[] = array_merge([$serviceId], $tagValues, [$definition->getClass()]); @@ -275,7 +283,7 @@ protected function describeContainerDefinition(Definition $definition, array $op $tagInformation = []; foreach ($tags as $tagName => $tagData) { foreach ($tagData as $tagParameters) { - $parameters = array_map(fn ($key, $value) => sprintf('%s: %s', $key, $value), array_keys($tagParameters), array_values($tagParameters)); + $parameters = array_map(fn ($key, $value) => sprintf('%s: %s', $key, \is_array($value) ? $this->formatParameter($value) : $value), array_keys($tagParameters), array_values($tagParameters)); $parameters = implode(', ', $parameters); if ('' === $parameters) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index daafc6011d3d0..cc9cfad683a72 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php @@ -169,6 +169,7 @@ public static function getContainerDefinitions() ->addTag('tag1', ['attr1' => 'val1', 'attr2' => 'val2']) ->addTag('tag1', ['attr3' => 'val3']) ->addTag('tag2') + ->addTag('tag3', ['array_attr' => ['foo', 'bar', [[[['ccc']]]]]]) ->addMethodCall('setMailer', [new Reference('mailer')]) ->setFactory([new Reference('factory.service'), 'get']), '.definition_3' => $definition3 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.json index 419ee67863813..f3b930983ab3e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.json @@ -36,6 +36,24 @@ { "name": "tag2", "parameters": [] + }, + { + "name": "tag3", + "parameters": { + "array_attr": [ + "foo", + "bar", + [ + [ + [ + [ + "ccc" + ] + ] + ] + ] + ] + } } ], "usages": [ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.md index d25978492e100..3ec9516a398ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.md @@ -24,4 +24,6 @@ - Tag: `tag1` - Attr3: val3 - Tag: `tag2` +- Tag: `tag3` + - Array_attr: ["foo","bar",[[[["ccc"]]]]] - Usages: .alias_2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt index 6ab25c269fcd9..46699413a99d6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.txt @@ -3,24 +3,26 @@ Information for Service ".service_2" ==================================== - ----------------- --------------------------------- -  Option   Value  - ----------------- --------------------------------- - Service ID .service_2 - Class Full\Qualified\Class2 - Tags tag1 (attr1: val1, attr2: val2) - tag1 (attr3: val3) - tag2 - Calls setMailer - Public no - Synthetic yes - Lazy no - Shared yes - Abstract no - Autowired no - Autoconfigured no - Required File /path/to/file - Factory Service factory.service - Factory Method get - Usages .alias_2 - ----------------- --------------------------------- + ----------------- ------------------------------------------------ +  Option   Value  + ----------------- ------------------------------------------------ + Service ID .service_2 + Class Full\Qualified\Class2 + Tags tag1 (attr1: val1, attr2: val2) + tag1 (attr3: val3) + tag2 + tag3 (array_attr: ["foo","bar",[[[["ccc"]]]]]) + Calls setMailer + Public no + Synthetic yes + Lazy no + Shared yes + Abstract no + Autowired no + Autoconfigured no + Required File /path/to/file + Factory Service factory.service + Factory Method get + Usages .alias_2 + ----------------- ------------------------------------------------ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.xml index f9d5c70c80171..aee83ef825506 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/alias_with_definition_2.xml @@ -14,6 +14,9 @@ val3 + + ["foo","bar",[[[["ccc"]]]]] + .alias_2 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json index 9bb716e442e17..ac6d122ce4539 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json @@ -33,6 +33,24 @@ { "name": "tag2", "parameters": [] + }, + { + "name": "tag3", + "parameters": { + "array_attr": [ + "foo", + "bar", + [ + [ + [ + [ + "ccc" + ] + ] + ] + ] + ] + } } ], "usages": [] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md index 3825ed8ebbba4..6dfab327d037a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md @@ -25,6 +25,8 @@ Definitions - Tag: `tag1` - Attr3: val3 - Tag: `tag2` +- Tag: `tag3` + - Array_attr: ["foo","bar",[[[["ccc"]]]]] - Usages: none ### .definition_3 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml index d3cf16a0f4c5a..84499f0845657 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml @@ -15,6 +15,9 @@ val3 + + ["foo","bar",[[[["ccc"]]]]] + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json index 66eb0af836225..5e60f26d170b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json @@ -33,6 +33,24 @@ { "name": "tag2", "parameters": [] + }, + { + "name": "tag3", + "parameters": { + "array_attr": [ + "foo", + "bar", + [ + [ + [ + [ + "ccc" + ] + ] + ] + ] + ] + } } ], "usages": [] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md index a76b77df04e55..aeae0d9f294ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md @@ -25,4 +25,6 @@ Definitions - Tag: `tag1` - Attr3: val3 - Tag: `tag2` +- Tag: `tag3` + - Array_attr: ["foo","bar",[[[["ccc"]]]]] - Usages: none diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml index b2929b01ac403..5413d7e5ea326 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml @@ -14,6 +14,9 @@ val3 + + ["foo","bar",[[[["ccc"]]]]] + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json index e0679f2cac58d..518f694ea3451 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json @@ -38,5 +38,25 @@ ], "usages": [] } + ], + "tag3": [ + { + "class": "Full\\Qualified\\Class2", + "public": false, + "synthetic": true, + "lazy": false, + "shared": true, + "abstract": false, + "autowire": false, + "autoconfigure": false, + "deprecated": false, + "file": "\/path\/to\/file", + "factory_service": "factory.service", + "factory_method": "get", + "calls": [ + "setMailer" + ], + "usages": [] + } ] } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md index f9558d326e7b3..80da2ddafd560 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md @@ -41,3 +41,24 @@ tag2 - Factory Method: `get` - Call: `setMailer` - Usages: none + + +tag3 +---- + +### .definition_2 + +- Class: `Full\Qualified\Class2` +- Public: no +- Synthetic: yes +- Lazy: no +- Shared: yes +- Abstract: no +- Autowired: no +- Autoconfigured: no +- Deprecated: no +- File: `/path/to/file` +- Factory Service: `factory.service` +- Factory Method: `get` +- Call: `setMailer` +- Usages: none diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.txt index b10e4661f6701..5be3bb0792754 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.txt @@ -12,3 +12,8 @@ * .definition_2 +"tag3" tag +---------- + + * .definition_2 + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml index 75a9714f5d8a6..1c68779f0ea71 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml @@ -16,4 +16,12 @@ + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json index 622904da2ef86..a661428c9cb08 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json @@ -31,6 +31,24 @@ { "name": "tag2", "parameters": [] + }, + { + "name": "tag3", + "parameters": { + "array_attr": [ + "foo", + "bar", + [ + [ + [ + [ + "ccc" + ] + ] + ] + ] + ] + } } ], "usages": [] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md index 376cbdb52348b..486f35fb77a27 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md @@ -17,4 +17,6 @@ - Tag: `tag1` - Attr3: val3 - Tag: `tag2` +- Tag: `tag3` + - Array_attr: ["foo","bar",[[[["ccc"]]]]] - Usages: none diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt index 2b8d3dde599e0..6fdb6d980942e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt @@ -1,22 +1,23 @@ - ----------------- --------------------------------- -  Option   Value  - ----------------- --------------------------------- - Service ID - - Class Full\Qualified\Class2 - Tags tag1 (attr1: val1, attr2: val2) - tag1 (attr3: val3) - tag2 - Calls setMailer - Public no - Synthetic yes - Lazy no - Shared yes - Abstract no - Autowired no - Autoconfigured no - Required File /path/to/file - Factory Service factory.service - Factory Method get - Usages none - ----------------- --------------------------------- + ----------------- ------------------------------------------------ +  Option   Value  + ----------------- ------------------------------------------------ + Service ID - + Class Full\Qualified\Class2 + Tags tag1 (attr1: val1, attr2: val2) + tag1 (attr3: val3) + tag2 + tag3 (array_attr: ["foo","bar",[[[["ccc"]]]]]) + Calls setMailer + Public no + Synthetic yes + Lazy no + Shared yes + Abstract no + Autowired no + Autoconfigured no + Required File /path/to/file + Factory Service factory.service + Factory Method get + Usages none + ----------------- ------------------------------------------------ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml index ab072f3e3adf5..4dd3ca0a0b619 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml @@ -13,5 +13,8 @@ val3 + + ["foo","bar",[[[["ccc"]]]]] + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.json index 20ef01a34b7a5..eeeb6f44a448b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.json @@ -32,6 +32,24 @@ { "name": "tag2", "parameters": [] + }, + { + "name": "tag3", + "parameters": { + "array_attr": [ + "foo", + "bar", + [ + [ + [ + [ + "ccc" + ] + ] + ] + ] + ] + } } ], "usages": [] diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.md index f5bf50e61764c..5b427bff5a26f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.md +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.md @@ -18,4 +18,6 @@ - Tag: `tag1` - Attr3: val3 - Tag: `tag2` +- Tag: `tag3` + - Array_attr: ["foo","bar",[[[["ccc"]]]]] - Usages: none diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt index 2b8d3dde599e0..43ca2cffa0ae3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.txt @@ -1,22 +1,23 @@ - ----------------- --------------------------------- -  Option   Value  - ----------------- --------------------------------- - Service ID - - Class Full\Qualified\Class2 - Tags tag1 (attr1: val1, attr2: val2) - tag1 (attr3: val3) - tag2 - Calls setMailer - Public no - Synthetic yes - Lazy no - Shared yes - Abstract no - Autowired no - Autoconfigured no - Required File /path/to/file - Factory Service factory.service - Factory Method get - Usages none - ----------------- --------------------------------- + ----------------- ------------------------------------------------ +  Option   Value  + ----------------- ------------------------------------------------ + Service ID - + Class Full\Qualified\Class2 + Tags tag1 (attr1: val1, attr2: val2) + tag1 (attr3: val3) + tag2 + tag3 (array_attr: ["foo","bar",[[[["ccc"]]]]]) + Calls setMailer + Public no + Synthetic yes + Lazy no + Shared yes + Abstract no + Autowired no + Autoconfigured no + Required File /path/to/file + Factory Service factory.service + Factory Method get + Usages none + ----------------- ------------------------------------------------ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.xml index ab072f3e3adf5..4dd3ca0a0b619 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_2.xml @@ -13,5 +13,8 @@ val3 + + ["foo","bar",[[[["ccc"]]]]] + From 35341187ba3ba6078552ff4e308b6a470b644491 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Sat, 16 Sep 2023 13:22:53 +0200 Subject: [PATCH 28/55] [Translator] Fix support for `default_path` in XML --- .../FrameworkBundle/Resources/config/schema/symfony-1.0.xsd | 1 + 1 file changed, 1 insertion(+) 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 29f64dad9bed9..faee50e2528a8 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 @@ -191,6 +191,7 @@ + From 9baf427ebe1b3d9fb9ea9617fb9eec7bbeaf5fd0 Mon Sep 17 00:00:00 2001 From: valtzu Date: Sat, 16 Sep 2023 18:53:06 +0300 Subject: [PATCH 29/55] Match next run timezone with from timezone --- .../Scheduler/Tests/Trigger/PeriodicalTriggerTest.php | 6 +++--- .../Component/Scheduler/Trigger/PeriodicalTrigger.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Scheduler/Tests/Trigger/PeriodicalTriggerTest.php b/src/Symfony/Component/Scheduler/Tests/Trigger/PeriodicalTriggerTest.php index e8dc8f49f735a..2e2df0fd9bc1d 100644 --- a/src/Symfony/Component/Scheduler/Tests/Trigger/PeriodicalTriggerTest.php +++ b/src/Symfony/Component/Scheduler/Tests/Trigger/PeriodicalTriggerTest.php @@ -23,9 +23,9 @@ class PeriodicalTriggerTest extends TestCase */ public function testConstructor(PeriodicalTrigger $trigger, bool $optimizable = true) { - $run = new \DateTimeImmutable('2922-02-22 13:34:00+00:00'); + $run = new \DateTimeImmutable('2922-02-22 12:34:00+00:00'); - $this->assertSame('2922-02-23 13:34:00+00:00', $trigger->getNextRunDate($run)->format('Y-m-d H:i:sP')); + $this->assertSame('2922-02-23 13:34:00+01:00', $trigger->getNextRunDate($run)->format('Y-m-d H:i:sP')); if ($optimizable) { // test that we are using the fast algorithm for short period of time @@ -37,7 +37,7 @@ public function testConstructor(PeriodicalTrigger $trigger, bool $optimizable = public static function provideForConstructor(): iterable { - $from = new \DateTimeImmutable($now = '2022-02-22 13:34:00+00:00'); + $from = new \DateTimeImmutable($now = '2022-02-22 13:34:00+01:00'); $until = new \DateTimeImmutable($farFuture = '3000-01-01'); yield [new PeriodicalTrigger(86400, $from, $until)]; diff --git a/src/Symfony/Component/Scheduler/Trigger/PeriodicalTrigger.php b/src/Symfony/Component/Scheduler/Trigger/PeriodicalTrigger.php index b7241c5c35be8..5115eb198ce84 100644 --- a/src/Symfony/Component/Scheduler/Trigger/PeriodicalTrigger.php +++ b/src/Symfony/Component/Scheduler/Trigger/PeriodicalTrigger.php @@ -97,7 +97,7 @@ public function getNextRunDate(\DateTimeImmutable $run): ?\DateTimeImmutable $delta = $run->format('U.u') - $from; $recurrencesPassed = floor($delta / $this->intervalInSeconds); $nextRunTimestamp = sprintf('%.6F', ($recurrencesPassed + 1) * $this->intervalInSeconds + $from); - $nextRun = \DateTimeImmutable::createFromFormat('U.u', $nextRunTimestamp, $fromDate->getTimezone()); + $nextRun = \DateTimeImmutable::createFromFormat('U.u', $nextRunTimestamp)->setTimezone($fromDate->getTimezone()); if ($this->from > $nextRun) { return $this->from; From 4d65f302bf0928fe2140f565091949ce986c4dc3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Mon, 18 Sep 2023 17:40:31 +0200 Subject: [PATCH 30/55] [SecurityBundle][PasswordHasher] Fix password migration with custom hasher service with security bundle config --- .../DependencyInjection/SecurityExtension.php | 5 +- .../SecurityExtensionTest.php | 27 ++++++++++ .../Hasher/PasswordHasherFactory.php | 50 ++++++++++++------- .../Hasher/PasswordHasherFactoryTest.php | 33 ++++++++++++ 4 files changed, 96 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index d64b2c38ac7e7..c165024b68d0d 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -848,7 +848,10 @@ private function createHasher(array $config) { // a custom hasher service if (isset($config['id'])) { - return new Reference($config['id']); + return $config['migrate_from'] ?? false ? [ + 'instance' => new Reference($config['id']), + 'migrate_from' => $config['migrate_from'], + ] : new Reference($config['id']); } if ($config['migrate_from'] ?? false) { diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 71ca327ca40c6..eef68e4c3de46 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -881,6 +881,33 @@ public function testLegacyAuthorizationManagerSignature() $this->assertEquals('%security.access.always_authenticate_before_granting%', (string) $args[3]); } + public function testCustomHasherWithMigrateFrom() + { + $container = $this->getRawContainer(); + + $container->loadFromExtension('security', [ + 'enable_authenticator_manager' => true, + 'password_hashers' => [ + 'legacy' => 'md5', + 'App\User' => [ + 'id' => 'App\Security\CustomHasher', + 'migrate_from' => 'legacy', + ], + ], + 'firewalls' => ['main' => ['http_basic' => true]], + ]); + + $container->compile(); + + $hashersMap = $container->getDefinition('security.password_hasher_factory')->getArgument(0); + + $this->assertArrayHasKey('App\User', $hashersMap); + $this->assertEquals($hashersMap['App\User'], [ + 'instance' => new Reference('App\Security\CustomHasher'), + 'migrate_from' => ['legacy'], + ]); + } + protected function getRawContainer() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php b/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php index dd7e015c1ecd2..116301c04a441 100644 --- a/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php +++ b/src/Symfony/Component/PasswordHasher/Hasher/PasswordHasherFactory.php @@ -71,6 +71,14 @@ public function getPasswordHasher($user): PasswordHasherInterface */ private function createHasher(array $config, bool $isExtra = false): PasswordHasherInterface { + if (isset($config['instance'])) { + if (!isset($config['migrate_from'])) { + return $config['instance']; + } + + $config = $this->getMigratingPasswordConfig($config); + } + if (isset($config['algorithm'])) { $rawConfig = $config; $config = $this->getHasherConfigFromAlgorithm($config); @@ -142,24 +150,8 @@ private function getHasherConfigFromAlgorithm(array $config): array ]; } - if ($frompasswordHashers = ($config['migrate_from'] ?? false)) { - unset($config['migrate_from']); - $hasherChain = [$this->createHasher($config, true)]; - - foreach ($frompasswordHashers as $name) { - if (isset($this->passwordHashers[$name])) { - $hasher = $this->createHasherUsingAdapter($name); - } else { - $hasher = $this->createHasher(['algorithm' => $name], true); - } - - $hasherChain[] = $hasher; - } - - return [ - 'class' => MigratingPasswordHasher::class, - 'arguments' => $hasherChain, - ]; + if ($config['migrate_from'] ?? false) { + return $this->getMigratingPasswordConfig($config); } switch ($config['algorithm']) { @@ -239,4 +231,26 @@ private function getHasherConfigFromAlgorithm(array $config): array ], ]; } + + private function getMigratingPasswordConfig(array $config): array + { + $frompasswordHashers = $config['migrate_from']; + unset($config['migrate_from']); + $hasherChain = [$this->createHasher($config, true)]; + + foreach ($frompasswordHashers as $name) { + if ($this->passwordHashers[$name] ?? false) { + $hasher = $this->createHasherUsingAdapter($name); + } else { + $hasher = $this->createHasher(['algorithm' => $name], true); + } + + $hasherChain[] = $hasher; + } + + return [ + 'class' => MigratingPasswordHasher::class, + 'arguments' => $hasherChain, + ]; + } } diff --git a/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php b/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php index 1f24a0d3cace2..1b97eedcdac48 100644 --- a/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php +++ b/src/Symfony/Component/PasswordHasher/Tests/Hasher/PasswordHasherFactoryTest.php @@ -49,6 +49,17 @@ public function testGetHasherWithService() $this->assertEquals($expectedHasher->hash('foo', ''), $hasher->hash('foo', '')); } + public function testGetHasherWithInstance() + { + $factory = new PasswordHasherFactory([ + PasswordAuthenticatedUserInterface::class => ['instance' => new MessageDigestPasswordHasher('sha1')], + ]); + + $hasher = $factory->getPasswordHasher($this->createMock(PasswordAuthenticatedUserInterface::class)); + $expectedHasher = new MessageDigestPasswordHasher('sha1'); + $this->assertEquals($expectedHasher->hash('foo', ''), $hasher->hash('foo', '')); + } + public function testGetHasherWithClassName() { $factory = new PasswordHasherFactory([ @@ -163,6 +174,28 @@ public function testMigrateFrom() $this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null)); } + public function testMigrateFromWithCustomInstance() + { + if (!SodiumPasswordHasher::isSupported()) { + $this->markTestSkipped('Sodium is not available'); + } + + $sodium = new SodiumPasswordHasher(); + + $factory = new PasswordHasherFactory([ + 'digest_hasher' => $digest = new MessageDigestPasswordHasher('sha256'), + SomeUser::class => ['instance' => $sodium, 'migrate_from' => ['bcrypt', 'digest_hasher']], + ]); + + $hasher = $factory->getPasswordHasher(SomeUser::class); + $this->assertInstanceOf(MigratingPasswordHasher::class, $hasher); + + $this->assertTrue($hasher->verify((new SodiumPasswordHasher())->hash('foo', null), 'foo', null)); + $this->assertTrue($hasher->verify((new NativePasswordHasher(null, null, null, \PASSWORD_BCRYPT))->hash('foo', null), 'foo', null)); + $this->assertTrue($hasher->verify($digest->hash('foo', null), 'foo', null)); + $this->assertStringStartsWith(\SODIUM_CRYPTO_PWHASH_STRPREFIX, $hasher->hash('foo', null)); + } + /** * @group legacy */ From 5ad2b5a6022d3aa51f52a2dae7d687ae57ce43b1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 18 Sep 2023 17:58:13 +0200 Subject: [PATCH 31/55] Update the PR template --- .github/PULL_REQUEST_TEMPLATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0dfc06eb7c16b..f56136de940d3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,14 +1,14 @@ | Q | A | ------------- | --- -| Branch? | 6.4 for features / 5.4, or 6.3 for bug fixes +| Branch? | 6.4 for features / 5.4 or 6.3 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no | Tickets | Fix #... | License | MIT -| Doc PR | symfony/symfony-docs#... +