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#... +

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


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy