From ba451ab7b2361dc65b18a85b7e50673e46603360 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 16 Jan 2021 12:55:47 +0100 Subject: [PATCH 01/50] improve failure messages of the CrawlerSelectorTextContains constraint --- .../Tests/Test/WebTestCaseTest.php | 4 ++-- .../Bundle/FrameworkBundle/composer.json | 2 +- .../Constraint/CrawlerSelectorTextContains.php | 17 ++++++++++++++--- .../CrawlerSelectorTextContainsTest.php | 15 +++++++++++---- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php index 50744192a9dfe..ff88b34007069 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Test/WebTestCaseTest.php @@ -183,7 +183,7 @@ public function testAssertSelectorTextNotContains() { $this->getCrawlerTester(new Crawler('

Foo'))->assertSelectorTextNotContains('body > h1', 'Bar'); $this->expectException(AssertionFailedError::class); - $this->expectExceptionMessage('matches selector "body > h1" and does not have a node matching selector "body > h1" with content containing "Foo".'); + $this->expectExceptionMessage('matches selector "body > h1" and the text "Foo" of the node matching selector "body > h1" does not contain "Foo".'); $this->getCrawlerTester(new Crawler('

Foo'))->assertSelectorTextNotContains('body > h1', 'Foo'); } @@ -199,7 +199,7 @@ public function testAssertPageTitleContains() { $this->getCrawlerTester(new Crawler('Foobar'))->assertPageTitleContains('Foo'); $this->expectException(AssertionFailedError::class); - $this->expectExceptionMessage('matches selector "title" and has a node matching selector "title" with content containing "Bar".'); + $this->expectExceptionMessage('matches selector "title" and the text "Foo" of the node matching selector "title" contains "Bar".'); $this->getCrawlerTester(new Crawler('<html><head><title>Foo'))->assertPageTitleContains('Bar'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index f592065b28cd7..d64e8e0390d62 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -38,7 +38,7 @@ "symfony/browser-kit": "^4.3|^5.0", "symfony/console": "^4.3.4|^5.0", "symfony/css-selector": "^3.4|^4.0|^5.0", - "symfony/dom-crawler": "^4.3|^5.0", + "symfony/dom-crawler": "^4.4.20|^5.2.4", "symfony/dotenv": "^4.3.6|^5.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/form": "^4.3.5|^5.0", diff --git a/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorTextContains.php b/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorTextContains.php index ffc6f5677cc5d..c4697ecf75376 100644 --- a/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorTextContains.php +++ b/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorTextContains.php @@ -18,6 +18,8 @@ final class CrawlerSelectorTextContains extends Constraint { private $selector; private $expectedText; + private $hasNode = false; + private $nodeText; public function __construct(string $selector, string $expectedText) { @@ -30,7 +32,11 @@ public function __construct(string $selector, string $expectedText) */ public function toString(): string { - return sprintf('has a node matching selector "%s" with content containing "%s"', $this->selector, $this->expectedText); + if ($this->hasNode) { + return sprintf('the text "%s" of the node matching selector "%s" contains "%s"', $this->nodeText, $this->selector, $this->expectedText); + } + + return sprintf('the Crawler has a node matching selector "%s"', $this->selector); } /** @@ -42,10 +48,15 @@ protected function matches($crawler): bool { $crawler = $crawler->filter($this->selector); if (!\count($crawler)) { + $this->hasNode = false; + return false; } - return false !== mb_strpos($crawler->text(null, true), $this->expectedText); + $this->hasNode = true; + $this->nodeText = $crawler->text(null, true); + + return false !== mb_strpos($this->nodeText, $this->expectedText); } /** @@ -55,6 +66,6 @@ protected function matches($crawler): bool */ protected function failureDescription($crawler): string { - return 'the Crawler '.$this->toString(); + return $this->toString(); } } diff --git a/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorTextContainsTest.php b/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorTextContainsTest.php index b92a13187bd5f..0d7656e589b49 100644 --- a/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorTextContainsTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorTextContainsTest.php @@ -24,15 +24,22 @@ public function testConstraint() $constraint = new CrawlerSelectorTextContains('title', 'Foo'); $this->assertTrue($constraint->evaluate(new Crawler('<html><head><title>Foobar'), '', true)); $this->assertFalse($constraint->evaluate(new Crawler('<html><head><title>Bar'), '', true)); + $this->assertFalse($constraint->evaluate(new Crawler('<html><head></head><body>Bar'), '', true)); try { $constraint->evaluate(new Crawler('<html><head><title>Bar')); - } catch (ExpectationFailedException $e) { - $this->assertEquals("Failed asserting that the Crawler has a node matching selector \"title\" with content containing \"Foo\".\n", TestFailure::exceptionToString($e)); - return; + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertEquals("Failed asserting that the text \"Bar\" of the node matching selector \"title\" contains \"Foo\".\n", TestFailure::exceptionToString($e)); } - $this->fail(); + try { + $constraint->evaluate(new Crawler('<html><head></head><body>Bar')); + + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertEquals("Failed asserting that the Crawler has a node matching selector \"title\".\n", TestFailure::exceptionToString($e)); + } } } From 6fd21ce5aa8679f900e1ad059c78967cd83e79c9 Mon Sep 17 00:00:00 2001 From: Simon Heimberg <simon.heimberg@heimberg-ea.ch> Date: Fri, 9 Apr 2021 13:10:44 +0300 Subject: [PATCH 02/50] allow null for framework.translator.default_path Allow to configure framework.translator.default_path to null, as it was until symfony 3.4.x (fix BC compatibility). fixes #37111 --- .../DependencyInjection/FrameworkExtension.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 972c8f255f2d6..814e54042cd6e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1213,7 +1213,9 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder $container->getDefinition('console.command.translation_update')->replaceArgument(6, $transPaths); } - if ($container->fileExists($defaultDir)) { + if (null === $defaultDir) { + // allow null + } elseif ($container->fileExists($defaultDir)) { $dirs[] = $defaultDir; } else { $nonExistingDirs[] = $defaultDir; From a1eb24bef2a773ca4fbaf135dae8fa33180d836a Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Tue, 27 Jul 2021 20:45:36 +0200 Subject: [PATCH 03/50] Add test for non-callable arrays as controllers Signed-off-by: Alexander M. Turek <me@derrabus.de> --- .../Routing/Loader/Configurator/Traits/RouteTrait.php | 2 +- src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php | 4 +++- .../Component/Routing/Tests/Fixtures/php_object_dsl.php | 4 +++- .../Component/Routing/Tests/Loader/PhpFileLoaderTest.php | 3 +++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php b/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php index 04009cd16d3a8..22df1af05469b 100644 --- a/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php +++ b/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php @@ -126,7 +126,7 @@ final public function methods(array $methods): self /** * Adds the "_controller" entry to defaults. * - * @param callable|string $controller a callable or parseable pseudo-callable + * @param callable|string|array $controller a callable or parseable pseudo-callable * * @return $this */ diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php b/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php index 86caa99696149..4208579476f68 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php @@ -9,7 +9,9 @@ ->condition('abc') ->options(['utf8' => true]) ->add('buz', 'zub') - ->controller('foo:act'); + ->controller('foo:act') + ->add('controller_class', '/controller') + ->controller(['Acme\MyApp\MyController', 'myAction']); $routes->import('php_dsl_sub.php') ->prefix('/sub') diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/php_object_dsl.php b/src/Symfony/Component/Routing/Tests/Fixtures/php_object_dsl.php index 9b9183a1b9427..6036dfd29ac08 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/php_object_dsl.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/php_object_dsl.php @@ -11,7 +11,9 @@ public function __invoke(RoutingConfigurator $routes) ->condition('abc') ->options(['utf8' => true]) ->add('buz', 'zub') - ->controller('foo:act'); + ->controller('foo:act') + ->add('controller_class', '/controller') + ->controller(['Acme\MyApp\MyController', 'myAction']); $routes->import('php_dsl_sub.php') ->prefix('/sub') diff --git a/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php index 70d45fc2383e8..f5f3a638e8067 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php @@ -174,6 +174,9 @@ public function testRoutingConfigurator() $expectedCollection->add('buz', (new Route('/zub')) ->setDefaults(['_controller' => 'foo:act']) ); + $expectedCollection->add('controller_class', (new Route('/controller')) + ->setDefaults(['_controller' => ['Acme\MyApp\MyController', 'myAction']]) + ); $expectedCollection->add('c_root', (new Route('/sub/pub/')) ->setRequirements(['id' => '\d+']) ); From 11e76c9d1f0a9ff28a2673e2c4208efbe071503b Mon Sep 17 00:00:00 2001 From: Fabien Potencier <fabien@potencier.org> Date: Thu, 29 Jul 2021 08:49:36 +0200 Subject: [PATCH 04/50] Bump Symfony version to 4.4.30 --- 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 321cca741b69d..7956190d279d6 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 $freshCache = []; - public const VERSION = '4.4.29'; - public const VERSION_ID = 40429; + public const VERSION = '4.4.30-DEV'; + public const VERSION_ID = 40430; public const MAJOR_VERSION = 4; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 29; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 30; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '11/2022'; public const END_OF_LIFE = '11/2023'; From fbaf499d1e59e5e4aea61d73b298647a537fb4df Mon Sep 17 00:00:00 2001 From: Christian Flothmann <christian.flothmann@qossmic.com> Date: Fri, 30 Jul 2021 10:55:43 +0200 Subject: [PATCH 05/50] remove 5.2 branch from PR template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 84dd98f43ad2b..62662f876fd3a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ | Q | A | ------------- | --- -| Branch? | 5.4 for features / 4.4, 5.2 or 5.3 for bug fixes <!-- see below --> +| Branch? | 5.4 for features / 4.4 or 5.3 for bug fixes <!-- see below --> | Bug fix? | yes/no | New feature? | yes/no <!-- please update src/**/CHANGELOG.md files --> | Deprecations? | yes/no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> From 28ae62d037f44ecb2ca84cb9a90a8d9a64c6c7be Mon Sep 17 00:00:00 2001 From: Bob van de Vijver <bobvandevijver@hotmail.com> Date: Thu, 29 Jul 2021 11:16:12 +0200 Subject: [PATCH 06/50] [Security] Fix str_contains type mismatch in ChannelListener --- .../Http/Firewall/ChannelListener.php | 2 +- .../Tests/Firewall/ChannelListenerTest.php | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php index b357564864cd0..71459406614ab 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ChannelListener.php @@ -51,7 +51,7 @@ public function supports(Request $request): ?bool if (null !== $this->logger) { if ('https' === $request->headers->get('X-Forwarded-Proto')) { $this->logger->info('Redirecting to HTTPS. ("X-Forwarded-Proto" header is set to "https" - did you set "trusted_proxies" correctly?)'); - } elseif (str_contains($request->headers->get('Forwarded'), 'proto=https')) { + } elseif (str_contains($request->headers->get('Forwarded', ''), 'proto=https')) { $this->logger->info('Redirecting to HTTPS. ("Forwarded" header is set to "proto=https" - did you set "trusted_proxies" correctly?)'); } else { $this->logger->info('Redirecting to HTTPS.'); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php index 5fab54c13227d..0153d30395d9c 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ChannelListenerTest.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Security\Http\Tests\Firewall; use PHPUnit\Framework\TestCase; +use Psr\Log\NullLogger; +use Symfony\Component\HttpFoundation\HeaderBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\RequestEvent; @@ -153,4 +155,29 @@ public function testHandleWithSecuredRequestAndHttpChannel() $this->assertSame($response, $event->getResponse()); } + + public function testSupportsWithoutHeaders() + { + $request = $this->createMock(Request::class); + $request + ->expects($this->any()) + ->method('isSecure') + ->willReturn(false) + ; + $request->headers = new HeaderBag(); + + $accessMap = $this->createMock(AccessMapInterface::class); + $accessMap + ->expects($this->any()) + ->method('getPatterns') + ->with($this->equalTo($request)) + ->willReturn([[], 'https']) + ; + + $entryPoint = $this->createMock(AuthenticationEntryPointInterface::class); + + $listener = new ChannelListener($accessMap, $entryPoint, new NullLogger()); + + $this->assertTrue($listener->supports($request)); + } } From 705f76571d586e7af8128fbf622c7d0435391f33 Mon Sep 17 00:00:00 2001 From: Christian Flothmann <christian.flothmann@qossmic.com> Date: Mon, 19 Jul 2021 11:58:14 +0200 Subject: [PATCH 07/50] always close open stopwatch section after handling kernel.request events --- .../Debug/TraceableEventDispatcher.php | 19 ++++++++++--------- .../Debug/TraceableEventDispatcherTest.php | 16 +++++++++------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php index ce4ddb35d3f75..832bfb58d0637 100644 --- a/src/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/HttpKernel/Debug/TraceableEventDispatcher.php @@ -30,6 +30,7 @@ protected function beforeDispatch(string $eventName, $event) { switch ($eventName) { case KernelEvents::REQUEST: + $event->getRequest()->attributes->set('_stopwatch_token', substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); $this->stopwatch->openSection(); break; case KernelEvents::VIEW: @@ -40,8 +41,8 @@ protected function beforeDispatch(string $eventName, $event) } break; case KernelEvents::TERMINATE: - $token = $event->getResponse()->headers->get('X-Debug-Token'); - if (null === $token) { + $sectionId = $event->getRequest()->attributes->get('_stopwatch_token'); + if (null === $sectionId) { break; } // There is a very special case when using built-in AppCache class as kernel wrapper, in the case @@ -50,7 +51,7 @@ protected function beforeDispatch(string $eventName, $event) // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception // which must be caught. try { - $this->stopwatch->openSection($token); + $this->stopwatch->openSection($sectionId); } catch (\LogicException $e) { } break; @@ -67,21 +68,21 @@ protected function afterDispatch(string $eventName, $event) $this->stopwatch->start('controller', 'section'); break; case KernelEvents::RESPONSE: - $token = $event->getResponse()->headers->get('X-Debug-Token'); - if (null === $token) { + $sectionId = $event->getRequest()->attributes->get('_stopwatch_token'); + if (null === $sectionId) { break; } - $this->stopwatch->stopSection($token); + $this->stopwatch->stopSection($sectionId); break; case KernelEvents::TERMINATE: // In the special case described in the `preDispatch` method above, the `$token` section // does not exist, then closing it throws an exception which must be caught. - $token = $event->getResponse()->headers->get('X-Debug-Token'); - if (null === $token) { + $sectionId = $event->getRequest()->attributes->get('_stopwatch_token'); + if (null === $sectionId) { break; } try { - $this->stopwatch->stopSection($token); + $this->stopwatch->stopSection($sectionId); } catch (\LogicException $e) { } break; diff --git a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php index 2fb050dafd9f9..90ea544b1abe2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php @@ -28,12 +28,12 @@ class TraceableEventDispatcherTest extends TestCase public function testStopwatchSections() { $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch = new Stopwatch()); - $kernel = $this->getHttpKernel($dispatcher, function () { return new Response('', 200, ['X-Debug-Token' => '292e1e']); }); + $kernel = $this->getHttpKernel($dispatcher); $request = Request::create('/'); $response = $kernel->handle($request); $kernel->terminate($request, $response); - $events = $stopwatch->getSectionEvents($response->headers->get('X-Debug-Token')); + $events = $stopwatch->getSectionEvents($request->attributes->get('_stopwatch_token')); $this->assertEquals([ '__section__', 'kernel.request', @@ -56,7 +56,7 @@ public function testStopwatchCheckControllerOnRequestEvent() $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch); - $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); }); + $kernel = $this->getHttpKernel($dispatcher); $request = Request::create('/'); $kernel->handle($request); } @@ -69,12 +69,12 @@ public function testStopwatchStopControllerOnRequestEvent() $stopwatch->expects($this->once()) ->method('isStarted') ->willReturn(true); - $stopwatch->expects($this->once()) + $stopwatch->expects($this->exactly(3)) ->method('stop'); $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch); - $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); }); + $kernel = $this->getHttpKernel($dispatcher); $request = Request::create('/'); $kernel->handle($request); } @@ -110,10 +110,12 @@ public function testListenerCanRemoveItselfWhenExecuted() $this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed'); } - protected function getHttpKernel($dispatcher, $controller) + protected function getHttpKernel($dispatcher) { $controllerResolver = $this->createMock(ControllerResolverInterface::class); - $controllerResolver->expects($this->once())->method('getController')->willReturn($controller); + $controllerResolver->expects($this->once())->method('getController')->willReturn(function () { + return new Response(); + }); $argumentResolver = $this->createMock(ArgumentResolverInterface::class); $argumentResolver->expects($this->once())->method('getArguments')->willReturn([]); From 4df1173b747adadc4cb26fbfa016e0245445af4f Mon Sep 17 00:00:00 2001 From: Oskar Stark <oskarstark@googlemail.com> Date: Sun, 1 Aug 2021 16:25:20 +0200 Subject: [PATCH 08/50] [Mailer][Sendgrid] Add previous exception --- .../Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php index 0134a6ff5ef7f..07108f19aab3c 100644 --- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php +++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php @@ -64,7 +64,7 @@ protected function doSendApi(SentMessage $sentMessage, Email $email, Envelope $e throw new HttpTransportException('Unable to send an email: '.implode('; ', array_column($result['errors'], 'message')).sprintf(' (code %d).', $statusCode), $response); } catch (DecodingExceptionInterface $e) { - throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response); + throw new HttpTransportException('Unable to send an email: '.$response->getContent(false).sprintf(' (code %d).', $statusCode), $response, 0, $e); } } From fb15542ecf6550de87d9bb772563e05ce8f7a65b Mon Sep 17 00:00:00 2001 From: Gocha Ossinkine <ossinkine@ya.ru> Date: Sun, 1 Aug 2021 21:24:46 +0500 Subject: [PATCH 09/50] [Validator] Update MIR card scheme --- .../Component/Validator/Constraints/CardSchemeValidator.php | 4 ++-- .../Validator/Tests/Constraints/CardSchemeValidatorTest.php | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php b/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php index 478047fb8f272..a63366f51a0a1 100644 --- a/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CardSchemeValidator.php @@ -77,9 +77,9 @@ class CardSchemeValidator extends ConstraintValidator '/^5[1-5][0-9]{14}$/', '/^2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12})$/', ], - // Payment system MIR numbers start with 220, then 1 digit from 0 to 4, then 12 digits + // Payment system MIR numbers start with 220, then 1 digit from 0 to 4, then between 12 and 15 digits 'MIR' => [ - '/^220[0-4][0-9]{12}$/', + '/^220[0-4][0-9]{12,15}$/', ], // All UATP card numbers start with a 1 and have a length of 15 digits. 'UATP' => [ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php index ddc9edb6c094d..de1850eafb39f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeValidatorTest.php @@ -104,6 +104,9 @@ public function getValidNumbers() ['MASTERCARD', '2709999999999999'], ['MASTERCARD', '2720995105105100'], ['MIR', '2200381427330082'], + ['MIR', '22003814273300821'], + ['MIR', '220038142733008212'], + ['MIR', '2200381427330082123'], ['UATP', '110165309696173'], ['VISA', '4111111111111111'], ['VISA', '4012888888881881'], @@ -136,7 +139,8 @@ public function getInvalidNumbers() ['MASTERCARD', '2721001234567890', CardScheme::INVALID_FORMAT_ERROR], // Not assigned yet ['MASTERCARD', '2220991234567890', CardScheme::INVALID_FORMAT_ERROR], // Not assigned yet ['UATP', '11016530969617', CardScheme::INVALID_FORMAT_ERROR], // invalid length - ['MIR', '22003814273300821', CardScheme::INVALID_FORMAT_ERROR], // invalid length + ['MIR', '220038142733008', CardScheme::INVALID_FORMAT_ERROR], // invalid length + ['MIR', '22003814273300821234', CardScheme::INVALID_FORMAT_ERROR], // invalid length ]; } } From 3eca446b21607ea1c7a865ece2dd8254c33679cc Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Mon, 26 Jul 2021 15:29:22 +0200 Subject: [PATCH 10/50] Fix return types for PHP 8.1 --- .../Constraints/UniqueEntityValidatorTest.php | 26 ++++++++++++++++--- .../Bundle/TwigBundle/TemplateIterator.php | 1 + .../Config/Resource/GlobResource.php | 1 + .../Component/Console/Helper/HelperSet.php | 3 ++- src/Symfony/Component/DomCrawler/Crawler.php | 2 ++ src/Symfony/Component/DomCrawler/Form.php | 4 +++ .../EventDispatcher/GenericEvent.php | 5 ++++ src/Symfony/Component/Finder/Finder.php | 2 ++ .../Finder/Iterator/CustomFilterIterator.php | 1 + .../Iterator/DateRangeFilterIterator.php | 1 + .../Iterator/DepthRangeFilterIterator.php | 1 + .../ExcludeDirectoryFilterIterator.php | 3 +++ .../Iterator/FileTypeFilterIterator.php | 1 + .../Iterator/FilecontentFilterIterator.php | 1 + .../Iterator/FilenameFilterIterator.php | 1 + .../Finder/Iterator/PathFilterIterator.php | 1 + .../Iterator/SizeRangeFilterIterator.php | 1 + .../Finder/Iterator/SortableIterator.php | 1 + .../Finder/Tests/Iterator/Iterator.php | 14 +++++++--- .../MultiplePcreFilterIteratorTest.php | 2 +- src/Symfony/Component/Form/Button.php | 6 +++++ src/Symfony/Component/Form/ButtonBuilder.php | 2 ++ .../Form/ChoiceList/View/ChoiceGroupView.php | 3 ++- .../ViolationMapper/ViolationPath.php | 1 + src/Symfony/Component/Form/Form.php | 6 +++++ src/Symfony/Component/Form/FormBuilder.php | 2 ++ .../Component/Form/FormErrorIterator.php | 13 ++++++++++ src/Symfony/Component/Form/FormView.php | 6 +++++ .../Form/Tests/Fixtures/CustomArrayObject.php | 11 +++++--- .../Form/Util/InheritDataAwareIterator.php | 2 ++ .../Component/Form/Util/OrderedHashMap.php | 6 +++++ .../Form/Util/OrderedHashMapIterator.php | 10 +++---- .../Component/HttpFoundation/File/Stream.php | 1 + .../Component/HttpFoundation/HeaderBag.php | 2 ++ .../Component/HttpFoundation/ParameterBag.php | 2 ++ .../Session/Attribute/AttributeBag.php | 2 ++ .../HttpFoundation/Session/Session.php | 2 ++ .../Handler/MemcachedSessionHandler.php | 2 ++ .../HttpFoundation/Tests/File/FakeFile.php | 10 +++---- .../Util/ArrayAccessibleResourceBundle.php | 12 +++------ .../Component/Intl/Data/Util/RingBuffer.php | 5 ++-- .../Ldap/Adapter/ExtLdap/Collection.php | 1 + .../OptionsResolver/OptionsResolver.php | 5 ++++ src/Symfony/Component/Process/InputStream.php | 1 + src/Symfony/Component/Process/Process.php | 1 + .../Component/PropertyAccess/PropertyPath.php | 1 + .../Fixtures/NonTraversableArrayObject.php | 11 +++++--- .../Tests/Fixtures/TraversableArrayObject.php | 9 +++++-- .../Component/Routing/RouteCollection.php | 2 ++ .../Exception/AuthenticationException.php | 2 +- .../Component/Templating/PhpEngine.php | 4 +++ .../Validator/ConstraintViolationList.php | 6 +++++ .../Tests/Fixtures/CustomArrayObject.php | 9 +++++-- .../Component/VarDumper/Cloner/Data.php | 6 +++++ 54 files changed, 194 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 05faff5872dd8..c0945114c9c23 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -827,6 +827,10 @@ public function resultWithEmptyIterator(): array return [ [$entity, new class() implements \Iterator { + /** + * @return mixed + */ + #[\ReturnTypeWillChange] public function current() { return null; @@ -837,19 +841,28 @@ public function valid(): bool return false; } - public function next() + public function next(): void { } + /** + * @return mixed + */ + #[\ReturnTypeWillChange] public function key() { + return false; } - public function rewind() + public function rewind(): void { } }], [$entity, new class() implements \Iterator { + /** + * @return mixed + */ + #[\ReturnTypeWillChange] public function current() { return false; @@ -860,15 +873,20 @@ public function valid(): bool return false; } - public function next() + public function next(): void { } + /** + * @return mixed + */ + #[\ReturnTypeWillChange] public function key() { + return false; } - public function rewind() + public function rewind(): void { } }], diff --git a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php index 8af15aa3a9f5f..b16eadc40bf54 100644 --- a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php +++ b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php @@ -45,6 +45,7 @@ public function __construct(KernelInterface $kernel, string $rootDir, array $pat /** * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { if (null !== $this->templates) { diff --git a/src/Symfony/Component/Config/Resource/GlobResource.php b/src/Symfony/Component/Config/Resource/GlobResource.php index 0b535682f4af3..f9429eb8f9bd9 100644 --- a/src/Symfony/Component/Config/Resource/GlobResource.php +++ b/src/Symfony/Component/Config/Resource/GlobResource.php @@ -102,6 +102,7 @@ public function __wakeup(): void /** * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { if (!file_exists($this->prefix) || (!$this->recursive && '' === $this->pattern)) { diff --git a/src/Symfony/Component/Console/Helper/HelperSet.php b/src/Symfony/Component/Console/Helper/HelperSet.php index d9d73f25fc69a..9aa1e67ba8c9b 100644 --- a/src/Symfony/Component/Console/Helper/HelperSet.php +++ b/src/Symfony/Component/Console/Helper/HelperSet.php @@ -98,8 +98,9 @@ public function getCommand() } /** - * @return Helper[] + * @return \Traversable<Helper> */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->helpers); diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index 3f5c2a50d6fec..de7b3aedc37ae 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -1149,6 +1149,7 @@ public function getNode($position) /** * @return int */ + #[\ReturnTypeWillChange] public function count() { return \count($this->nodes); @@ -1157,6 +1158,7 @@ public function count() /** * @return \ArrayIterator|\DOMNode[] */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->nodes); diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index dbba779ced5d0..0c86116a64eca 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -321,6 +321,7 @@ public function all() * * @return bool true if the field exists, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->has($name); @@ -335,6 +336,7 @@ public function offsetExists($name) * * @throws \InvalidArgumentException if the field does not exist */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->fields->get($name); @@ -350,6 +352,7 @@ public function offsetGet($name) * * @throws \InvalidArgumentException if the field does not exist */ + #[\ReturnTypeWillChange] public function offsetSet($name, $value) { $this->fields->set($name, $value); @@ -362,6 +365,7 @@ public function offsetSet($name, $value) * * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { $this->fields->remove($name); diff --git a/src/Symfony/Component/EventDispatcher/GenericEvent.php b/src/Symfony/Component/EventDispatcher/GenericEvent.php index d86a584153ded..23333bc21284f 100644 --- a/src/Symfony/Component/EventDispatcher/GenericEvent.php +++ b/src/Symfony/Component/EventDispatcher/GenericEvent.php @@ -123,6 +123,7 @@ public function hasArgument($key) * * @throws \InvalidArgumentException if key does not exist in $this->args */ + #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->getArgument($key); @@ -136,6 +137,7 @@ public function offsetGet($key) * * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($key, $value) { $this->setArgument($key, $value); @@ -148,6 +150,7 @@ public function offsetSet($key, $value) * * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($key) { if ($this->hasArgument($key)) { @@ -162,6 +165,7 @@ public function offsetUnset($key) * * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($key) { return $this->hasArgument($key); @@ -172,6 +176,7 @@ public function offsetExists($key) * * @return \ArrayIterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->arguments); diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 92249ad902178..e1194ed695e23 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -618,6 +618,7 @@ public function in($dirs) * * @throws \LogicException if the in() method has not been called */ + #[\ReturnTypeWillChange] public function getIterator() { if (0 === \count($this->dirs) && 0 === \count($this->iterators)) { @@ -702,6 +703,7 @@ public function hasResults() * * @return int */ + #[\ReturnTypeWillChange] public function count() { return iterator_count($this->getIterator()); diff --git a/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php b/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php index a30bbd0b9d265..f85cb7bffb772 100644 --- a/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php @@ -46,6 +46,7 @@ public function __construct(\Iterator $iterator, array $filters) * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); diff --git a/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php index 2e97e00d37456..90616f471b1f7 100644 --- a/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php @@ -38,6 +38,7 @@ public function __construct(\Iterator $iterator, array $comparators) * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); diff --git a/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php index 18e751d77b928..e96fefd961b16 100644 --- a/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php @@ -38,6 +38,7 @@ public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { return $this->getInnerIterator()->getDepth() >= $this->minDepth; diff --git a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php index 366ad70cdb9bc..cf9e678771da9 100644 --- a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -52,6 +52,7 @@ public function __construct(\Iterator $iterator, array $directories) * * @return bool True if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) { @@ -71,6 +72,7 @@ public function accept() /** * @return bool */ + #[\ReturnTypeWillChange] public function hasChildren() { return $this->isRecursive && $this->iterator->hasChildren(); @@ -79,6 +81,7 @@ public function hasChildren() /** * @return self */ + #[\ReturnTypeWillChange] public function getChildren() { $children = new self($this->iterator->getChildren(), []); diff --git a/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php index 0ea2c508802de..d054cefb9fff9 100644 --- a/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php @@ -39,6 +39,7 @@ public function __construct(\Iterator $iterator, int $mode) * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); diff --git a/src/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php index 81594b8774048..41eb767f7a651 100644 --- a/src/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FilecontentFilterIterator.php @@ -24,6 +24,7 @@ class FilecontentFilterIterator extends MultiplePcreFilterIterator * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { if (!$this->matchRegexps && !$this->noMatchRegexps) { diff --git a/src/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php index e168cd8ffa798..8365756c15209 100644 --- a/src/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FilenameFilterIterator.php @@ -25,6 +25,7 @@ class FilenameFilterIterator extends MultiplePcreFilterIterator * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { return $this->isAccepted($this->current()->getFilename()); diff --git a/src/Symfony/Component/Finder/Iterator/PathFilterIterator.php b/src/Symfony/Component/Finder/Iterator/PathFilterIterator.php index 3fda557be366b..f4aaa1fb0027d 100644 --- a/src/Symfony/Component/Finder/Iterator/PathFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/PathFilterIterator.php @@ -24,6 +24,7 @@ class PathFilterIterator extends MultiplePcreFilterIterator * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { $filename = $this->current()->getRelativePathname(); diff --git a/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php index 2aeef67b87f73..4078f3692e052 100644 --- a/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php @@ -38,6 +38,7 @@ public function __construct(\Iterator $iterator, array $comparators) * * @return bool true if the value should be kept, false otherwise */ + #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); diff --git a/src/Symfony/Component/Finder/Iterator/SortableIterator.php b/src/Symfony/Component/Finder/Iterator/SortableIterator.php index 8559ba51cd794..adc7e999db8b4 100644 --- a/src/Symfony/Component/Finder/Iterator/SortableIterator.php +++ b/src/Symfony/Component/Finder/Iterator/SortableIterator.php @@ -81,6 +81,7 @@ public function __construct(\Traversable $iterator, $sort, bool $reverseOrder = /** * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { if (1 === $this->sort) { diff --git a/src/Symfony/Component/Finder/Tests/Iterator/Iterator.php b/src/Symfony/Component/Finder/Tests/Iterator/Iterator.php index bc2eb53b393e0..108c66a273c99 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/Iterator.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/Iterator.php @@ -23,12 +23,12 @@ public function __construct(array $values = []) $this->rewind(); } - public function attach(\SplFileInfo $fileinfo) + public function attach(\SplFileInfo $fileinfo): void { $this->values[] = $fileinfo; } - public function rewind() + public function rewind(): void { reset($this->values); } @@ -38,16 +38,24 @@ public function valid(): bool return false !== $this->current(); } - public function next() + public function next(): void { next($this->values); } + /** + * @return mixed + */ + #[\ReturnTypeWillChange] public function current() { return current($this->values); } + /** + * @return mixed + */ + #[\ReturnTypeWillChange] public function key() { return key($this->values); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php index 15e069b9f81c1..590aea21af693 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/MultiplePcreFilterIteratorTest.php @@ -54,7 +54,7 @@ public function __construct() { } - public function accept() + public function accept(): bool { throw new \BadFunctionCallException('Not implemented'); } diff --git a/src/Symfony/Component/Form/Button.php b/src/Symfony/Component/Form/Button.php index f3f1edebf10d2..9c3cf9b6b5976 100644 --- a/src/Symfony/Component/Form/Button.php +++ b/src/Symfony/Component/Form/Button.php @@ -51,6 +51,7 @@ public function __construct(FormConfigInterface $config) * * @return bool Always returns false */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return false; @@ -67,6 +68,7 @@ public function offsetExists($offset) * * @throws BadMethodCallException */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { throw new BadMethodCallException('Buttons cannot have children.'); @@ -84,6 +86,7 @@ public function offsetGet($offset) * * @throws BadMethodCallException */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { throw new BadMethodCallException('Buttons cannot have children.'); @@ -100,6 +103,7 @@ public function offsetSet($offset, $value) * * @throws BadMethodCallException */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { throw new BadMethodCallException('Buttons cannot have children.'); @@ -436,6 +440,7 @@ public function createView(FormView $parent = null) * * @return int Always returns 0 */ + #[\ReturnTypeWillChange] public function count() { return 0; @@ -446,6 +451,7 @@ public function count() * * @return \EmptyIterator Always returns an empty iterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new \EmptyIterator(); diff --git a/src/Symfony/Component/Form/ButtonBuilder.php b/src/Symfony/Component/Form/ButtonBuilder.php index 4d16632bbe40d..fb310899700f8 100644 --- a/src/Symfony/Component/Form/ButtonBuilder.php +++ b/src/Symfony/Component/Form/ButtonBuilder.php @@ -717,6 +717,7 @@ public function getOption($name, $default = null) * * @return int Always returns 0 */ + #[\ReturnTypeWillChange] public function count() { return 0; @@ -727,6 +728,7 @@ public function count() * * @return \EmptyIterator Always returns an empty iterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new \EmptyIterator(); diff --git a/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php b/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php index dd80486c9acea..a8446655c3565 100644 --- a/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php +++ b/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php @@ -36,8 +36,9 @@ public function __construct($label, array $choices = []) /** * {@inheritdoc} * - * @return self[]|ChoiceView[] + * @return \Traversable<ChoiceGroupView|ChoiceView> */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->choices); diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php index fca0bfa16b6b3..47593b82cb1ff 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php @@ -223,6 +223,7 @@ public function mapsForm($index) * * @return ViolationPathIterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new ViolationPathIterator($this); diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 9abb6bdeab146..32cc437574d4b 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -958,6 +958,7 @@ public function get($name) * * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return $this->has($name); @@ -972,6 +973,7 @@ public function offsetExists($name) * * @throws OutOfBoundsException if the named child does not exist */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->get($name); @@ -990,6 +992,7 @@ public function offsetGet($name) * * @see self::add() */ + #[\ReturnTypeWillChange] public function offsetSet($name, $child) { $this->add($child); @@ -1004,6 +1007,7 @@ public function offsetSet($name, $child) * * @throws AlreadySubmittedException if the form has already been submitted */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { $this->remove($name); @@ -1014,6 +1018,7 @@ public function offsetUnset($name) * * @return \Traversable<FormInterface> */ + #[\ReturnTypeWillChange] public function getIterator() { return $this->children; @@ -1024,6 +1029,7 @@ public function getIterator() * * @return int The number of embedded form children */ + #[\ReturnTypeWillChange] public function count() { return \count($this->children); diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php index 2fa65e095c496..9ec863ac493c8 100644 --- a/src/Symfony/Component/Form/FormBuilder.php +++ b/src/Symfony/Component/Form/FormBuilder.php @@ -161,6 +161,7 @@ public function all() /** * @return int */ + #[\ReturnTypeWillChange] public function count() { if ($this->locked) { @@ -215,6 +216,7 @@ public function getForm() * * @return FormBuilderInterface[]|\Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { if ($this->locked) { diff --git a/src/Symfony/Component/Form/FormErrorIterator.php b/src/Symfony/Component/Form/FormErrorIterator.php index f4614844985a0..0ef5a2e95844c 100644 --- a/src/Symfony/Component/Form/FormErrorIterator.php +++ b/src/Symfony/Component/Form/FormErrorIterator.php @@ -93,6 +93,7 @@ public function getForm() * * @return FormError|self An error or an iterator containing nested errors */ + #[\ReturnTypeWillChange] public function current() { return current($this->errors); @@ -101,6 +102,7 @@ public function current() /** * Advances the iterator to the next position. */ + #[\ReturnTypeWillChange] public function next() { next($this->errors); @@ -111,6 +113,7 @@ public function next() * * @return int The 0-indexed position */ + #[\ReturnTypeWillChange] public function key() { return key($this->errors); @@ -121,6 +124,7 @@ public function key() * * @return bool Whether the iterator is valid */ + #[\ReturnTypeWillChange] public function valid() { return null !== key($this->errors); @@ -132,6 +136,7 @@ public function valid() * This method detects if errors have been added to the form since the * construction of the iterator. */ + #[\ReturnTypeWillChange] public function rewind() { reset($this->errors); @@ -144,6 +149,7 @@ public function rewind() * * @return bool Whether that position exists */ + #[\ReturnTypeWillChange] public function offsetExists($position) { return isset($this->errors[$position]); @@ -158,6 +164,7 @@ public function offsetExists($position) * * @throws OutOfBoundsException If the given position does not exist */ + #[\ReturnTypeWillChange] public function offsetGet($position) { if (!isset($this->errors[$position])) { @@ -174,6 +181,7 @@ public function offsetGet($position) * * @throws BadMethodCallException */ + #[\ReturnTypeWillChange] public function offsetSet($position, $value) { throw new BadMethodCallException('The iterator doesn\'t support modification of elements.'); @@ -186,6 +194,7 @@ public function offsetSet($position, $value) * * @throws BadMethodCallException */ + #[\ReturnTypeWillChange] public function offsetUnset($position) { throw new BadMethodCallException('The iterator doesn\'t support modification of elements.'); @@ -197,6 +206,7 @@ public function offsetUnset($position) * * @return bool Whether the current element is an instance of this class */ + #[\ReturnTypeWillChange] public function hasChildren() { return current($this->errors) instanceof self; @@ -207,6 +217,7 @@ public function hasChildren() * * @return self */ + #[\ReturnTypeWillChange] public function getChildren() { return current($this->errors); @@ -229,6 +240,7 @@ public function getChildren() * * @return int The number of iterated elements */ + #[\ReturnTypeWillChange] public function count() { return \count($this->errors); @@ -243,6 +255,7 @@ public function count() * * @throws OutOfBoundsException If the position is invalid */ + #[\ReturnTypeWillChange] public function seek($position) { if (!isset($this->errors[$position])) { diff --git a/src/Symfony/Component/Form/FormView.php b/src/Symfony/Component/Form/FormView.php index 644bf515e6a71..460e52857680d 100644 --- a/src/Symfony/Component/Form/FormView.php +++ b/src/Symfony/Component/Form/FormView.php @@ -108,6 +108,7 @@ public function setMethodRendered() * * @return self The child view */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->children[$name]; @@ -120,6 +121,7 @@ public function offsetGet($name) * * @return bool Whether the child view exists */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->children[$name]); @@ -132,6 +134,7 @@ public function offsetExists($name) * * @throws BadMethodCallException always as setting a child by name is not allowed */ + #[\ReturnTypeWillChange] public function offsetSet($name, $value) { throw new BadMethodCallException('Not supported.'); @@ -144,6 +147,7 @@ public function offsetSet($name, $value) * * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { unset($this->children[$name]); @@ -154,6 +158,7 @@ public function offsetUnset($name) * * @return \ArrayIterator<string, FormView> The iterator */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->children); @@ -164,6 +169,7 @@ public function getIterator() * * @return int The number of children views */ + #[\ReturnTypeWillChange] public function count() { return \count($this->children); diff --git a/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php b/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php index 5c12b6b400bb8..41cb5af4cdf7b 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php @@ -29,12 +29,17 @@ public function offsetExists($offset): bool return \array_key_exists($offset, $this->array); } + /** + * @param mixed $offset + * @return mixed + */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->array[$offset]; } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { if (null === $offset) { $this->array[] = $value; @@ -43,7 +48,7 @@ public function offsetSet($offset, $value) } } - public function offsetUnset($offset) + public function offsetUnset($offset): void { unset($this->array[$offset]); } @@ -73,7 +78,7 @@ public function __unserialize(array $data): void $this->array = $data; } - public function unserialize($serialized) + public function unserialize($serialized): void { $this->__unserialize((array) unserialize((string) $serialized)); } diff --git a/src/Symfony/Component/Form/Util/InheritDataAwareIterator.php b/src/Symfony/Component/Form/Util/InheritDataAwareIterator.php index 1bb324423623b..7cba17dbebe1c 100644 --- a/src/Symfony/Component/Form/Util/InheritDataAwareIterator.php +++ b/src/Symfony/Component/Form/Util/InheritDataAwareIterator.php @@ -30,6 +30,7 @@ class InheritDataAwareIterator extends \IteratorIterator implements \RecursiveIt * * @return static */ + #[\ReturnTypeWillChange] public function getChildren() { return new static($this->current()); @@ -38,6 +39,7 @@ public function getChildren() /** * @return bool */ + #[\ReturnTypeWillChange] public function hasChildren() { return (bool) $this->current()->getConfig()->getInheritData(); diff --git a/src/Symfony/Component/Form/Util/OrderedHashMap.php b/src/Symfony/Component/Form/Util/OrderedHashMap.php index 7b1ca264d2bbb..b60a7ce4b0959 100644 --- a/src/Symfony/Component/Form/Util/OrderedHashMap.php +++ b/src/Symfony/Component/Form/Util/OrderedHashMap.php @@ -101,6 +101,7 @@ public function __construct(array $elements = []) /** * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($key) { return isset($this->elements[$key]); @@ -111,6 +112,7 @@ public function offsetExists($key) * * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($key) { if (!isset($this->elements[$key])) { @@ -125,6 +127,7 @@ public function offsetGet($key) * * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($key, $value) { if (null === $key || !isset($this->elements[$key])) { @@ -148,6 +151,7 @@ public function offsetSet($key, $value) * * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($key) { if (false !== ($position = array_search((string) $key, $this->orderedKeys))) { @@ -165,6 +169,7 @@ public function offsetUnset($key) /** * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { return new OrderedHashMapIterator($this->elements, $this->orderedKeys, $this->managedCursors); @@ -173,6 +178,7 @@ public function getIterator() /** * @return int */ + #[\ReturnTypeWillChange] public function count() { return \count($this->elements); diff --git a/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php b/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php index 6e295e1871451..87cab46052b40 100644 --- a/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php +++ b/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php @@ -105,6 +105,7 @@ public function __destruct() * * @return mixed */ + #[\ReturnTypeWillChange] public function current() { return $this->current; @@ -112,10 +113,8 @@ public function current() /** * {@inheritdoc} - * - * @return void */ - public function next() + public function next(): void { ++$this->cursor; @@ -133,6 +132,7 @@ public function next() * * @return mixed */ + #[\ReturnTypeWillChange] public function key() { if (null === $this->key) { @@ -154,10 +154,8 @@ public function valid(): bool /** * {@inheritdoc} - * - * @return void */ - public function rewind() + public function rewind(): void { $this->cursor = 0; diff --git a/src/Symfony/Component/HttpFoundation/File/Stream.php b/src/Symfony/Component/HttpFoundation/File/Stream.php index 4a08e7f2dd355..cef3e03977cfe 100644 --- a/src/Symfony/Component/HttpFoundation/File/Stream.php +++ b/src/Symfony/Component/HttpFoundation/File/Stream.php @@ -23,6 +23,7 @@ class Stream extends File * * @return int|false */ + #[\ReturnTypeWillChange] public function getSize() { return false; diff --git a/src/Symfony/Component/HttpFoundation/HeaderBag.php b/src/Symfony/Component/HttpFoundation/HeaderBag.php index 15393544fcbfe..9fb113de44e26 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/HeaderBag.php @@ -279,6 +279,7 @@ public function removeCacheControlDirective($key) * * @return \ArrayIterator An \ArrayIterator instance */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->headers); @@ -289,6 +290,7 @@ public function getIterator() * * @return int The number of headers */ + #[\ReturnTypeWillChange] public function count() { return \count($this->headers); diff --git a/src/Symfony/Component/HttpFoundation/ParameterBag.php b/src/Symfony/Component/HttpFoundation/ParameterBag.php index 1de753d3da37b..a2fe0af869873 100644 --- a/src/Symfony/Component/HttpFoundation/ParameterBag.php +++ b/src/Symfony/Component/HttpFoundation/ParameterBag.php @@ -210,6 +210,7 @@ public function filter($key, $default = null, $filter = \FILTER_DEFAULT, $option * * @return \ArrayIterator An \ArrayIterator instance */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->parameters); @@ -220,6 +221,7 @@ public function getIterator() * * @return int The number of parameters */ + #[\ReturnTypeWillChange] public function count() { return \count($this->parameters); diff --git a/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php b/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php index ee33698cf0842..bd35531739d3c 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php @@ -131,6 +131,7 @@ public function clear() * * @return \ArrayIterator An \ArrayIterator instance */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->attributes); @@ -141,6 +142,7 @@ public function getIterator() * * @return int The number of attributes */ + #[\ReturnTypeWillChange] public function count() { return \count($this->attributes); diff --git a/src/Symfony/Component/HttpFoundation/Session/Session.php b/src/Symfony/Component/HttpFoundation/Session/Session.php index 960679ace8f61..f42ed38ef5573 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Session.php +++ b/src/Symfony/Component/HttpFoundation/Session/Session.php @@ -126,6 +126,7 @@ public function isStarted() * * @return \ArrayIterator An \ArrayIterator instance */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->getAttributeBag()->all()); @@ -136,6 +137,7 @@ public function getIterator() * * @return int */ + #[\ReturnTypeWillChange] public function count() { return \count($this->getAttributeBag()->all()); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index d8663a57b76d2..af9d45cae3b40 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -57,6 +57,7 @@ public function __construct(\Memcached $memcached, array $options = []) /** * @return bool */ + #[\ReturnTypeWillChange] public function close() { return $this->memcached->quit(); @@ -73,6 +74,7 @@ protected function doRead($sessionId) /** * @return bool */ + #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { $this->memcached->touch($this->prefix.$sessionId, time() + $this->ttl); diff --git a/src/Symfony/Component/HttpFoundation/Tests/File/FakeFile.php b/src/Symfony/Component/HttpFoundation/Tests/File/FakeFile.php index c415989f2f7f8..8b2f12f4144cf 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/File/FakeFile.php +++ b/src/Symfony/Component/HttpFoundation/Tests/File/FakeFile.php @@ -17,28 +17,28 @@ class FakeFile extends OrigFile { private $realpath; - public function __construct($realpath, $path) + public function __construct(string $realpath, string $path) { $this->realpath = $realpath; parent::__construct($path, false); } - public function isReadable() + public function isReadable(): bool { return true; } - public function getRealpath() + public function getRealpath(): string { return $this->realpath; } - public function getSize() + public function getSize(): int { return 42; } - public function getMTime() + public function getMTime(): int { return time(); } diff --git a/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php b/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php index da6faf67810b6..2679948b14733 100644 --- a/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php +++ b/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php @@ -45,25 +45,21 @@ public function offsetExists($offset): bool } /** + * @param mixed $offset * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->get($offset); } - /** - * @return void - */ - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { throw new BadMethodCallException('Resource bundles cannot be modified.'); } - /** - * @return void - */ - public function offsetUnset($offset) + public function offsetUnset($offset): void { throw new BadMethodCallException('Resource bundles cannot be modified.'); } diff --git a/src/Symfony/Component/Intl/Data/Util/RingBuffer.php b/src/Symfony/Component/Intl/Data/Util/RingBuffer.php index 76bca285bbbc2..72d86025f718a 100644 --- a/src/Symfony/Component/Intl/Data/Util/RingBuffer.php +++ b/src/Symfony/Component/Intl/Data/Util/RingBuffer.php @@ -52,6 +52,7 @@ public function offsetExists($key): bool * * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($key) { if (!isset($this->indices[$key])) { @@ -66,7 +67,7 @@ public function offsetGet($key) * * @return void */ - public function offsetSet($key, $value) + public function offsetSet($key, $value): void { if (false !== ($keyToRemove = array_search($this->cursor, $this->indices))) { unset($this->indices[$keyToRemove]); @@ -83,7 +84,7 @@ public function offsetSet($key, $value) * * @return void */ - public function offsetUnset($key) + public function offsetUnset($key): void { if (isset($this->indices[$key])) { $this->values[$this->indices[$key]] = null; diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php index 05e81c8378e57..d8da8ddbf6586 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php @@ -45,6 +45,7 @@ public function toArray() /** * @return int */ + #[\ReturnTypeWillChange] public function count() { $con = $this->connection->getResource(); diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php index 6c6764e1818bd..fc1cf85475861 100644 --- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php +++ b/src/Symfony/Component/OptionsResolver/OptionsResolver.php @@ -832,6 +832,7 @@ public function resolve(array $options = []) * @throws OptionDefinitionException If there is a cyclic dependency between * lazy options and/or normalizers */ + #[\ReturnTypeWillChange] public function offsetGet($option/*, bool $triggerDeprecation = true*/) { if (!$this->locked) { @@ -1072,6 +1073,7 @@ private function verifyTypes(string $type, $value, array &$invalidTypes, int $le * * @see \ArrayAccess::offsetExists() */ + #[\ReturnTypeWillChange] public function offsetExists($option) { if (!$this->locked) { @@ -1088,6 +1090,7 @@ public function offsetExists($option) * * @throws AccessException */ + #[\ReturnTypeWillChange] public function offsetSet($option, $value) { throw new AccessException('Setting options via array access is not supported. Use setDefault() instead.'); @@ -1100,6 +1103,7 @@ public function offsetSet($option, $value) * * @throws AccessException */ + #[\ReturnTypeWillChange] public function offsetUnset($option) { throw new AccessException('Removing options via array access is not supported. Use remove() instead.'); @@ -1116,6 +1120,7 @@ public function offsetUnset($option) * * @see \Countable::count() */ + #[\ReturnTypeWillChange] public function count() { if (!$this->locked) { diff --git a/src/Symfony/Component/Process/InputStream.php b/src/Symfony/Component/Process/InputStream.php index c86fca86878df..4f8f71331aafc 100644 --- a/src/Symfony/Component/Process/InputStream.php +++ b/src/Symfony/Component/Process/InputStream.php @@ -69,6 +69,7 @@ public function isClosed() /** * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { $this->open = true; diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index a30cc3d118e0e..9fafddd64413d 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -622,6 +622,7 @@ public function getIncrementalOutput() * * @return \Generator */ + #[\ReturnTypeWillChange] public function getIterator($flags = 0) { $this->readPipesForOutput(__FUNCTION__, false); diff --git a/src/Symfony/Component/PropertyAccess/PropertyPath.php b/src/Symfony/Component/PropertyAccess/PropertyPath.php index f831ec3fda0bb..ac1f7c3c04cf4 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPath.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPath.php @@ -154,6 +154,7 @@ public function getParent() * * @return PropertyPathIteratorInterface */ + #[\ReturnTypeWillChange] public function getIterator() { return new PropertyPathIterator($this); diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php index cf02ee69f2979..da8911ed7207f 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php @@ -29,12 +29,17 @@ public function offsetExists($offset): bool return \array_key_exists($offset, $this->array); } + /** + * @param mixed $offset + * @return mixed + */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->array[$offset]; } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { if (null === $offset) { $this->array[] = $value; @@ -43,7 +48,7 @@ public function offsetSet($offset, $value) } } - public function offsetUnset($offset) + public function offsetUnset($offset): void { unset($this->array[$offset]); } @@ -68,7 +73,7 @@ public function __unserialize(array $data): void $this->array = $data; } - public function unserialize($serialized) + public function unserialize($serialized): void { $this->__unserialize((array) unserialize((string) $serialized)); } diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php index 5693c6b73e685..26ab98575f25f 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php @@ -29,12 +29,17 @@ public function offsetExists($offset): bool return \array_key_exists($offset, $this->array); } + /** + * @param mixed $offset + * @return mixed + */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->array[$offset]; } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { if (null === $offset) { $this->array[] = $value; @@ -43,7 +48,7 @@ public function offsetSet($offset, $value) } } - public function offsetUnset($offset) + public function offsetUnset($offset): void { unset($this->array[$offset]); } diff --git a/src/Symfony/Component/Routing/RouteCollection.php b/src/Symfony/Component/Routing/RouteCollection.php index 3baf0986c5cb1..56e925cac5158 100644 --- a/src/Symfony/Component/Routing/RouteCollection.php +++ b/src/Symfony/Component/Routing/RouteCollection.php @@ -51,6 +51,7 @@ public function __clone() * * @return \ArrayIterator|Route[] An \ArrayIterator object for iterating over routes */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->routes); @@ -61,6 +62,7 @@ public function getIterator() * * @return int The number of routes */ + #[\ReturnTypeWillChange] public function count() { return \count($this->routes); diff --git a/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php b/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php index 8a1c8327087dc..04a1212e21bfb 100644 --- a/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php +++ b/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php @@ -128,7 +128,7 @@ public function __sleep(): array /** * @internal */ - public function __wakeup() + public function __wakeup(): void { if (__CLASS__ !== $c = (new \ReflectionMethod($this, 'unserialize'))->getDeclaringClass()->name) { @trigger_error(sprintf('Implementing the "%s::unserialize()" method is deprecated since Symfony 4.3, implement the __serialize() and __unserialize() methods instead.', $c), \E_USER_DEPRECATED); diff --git a/src/Symfony/Component/Templating/PhpEngine.php b/src/Symfony/Component/Templating/PhpEngine.php index b849da174b5f8..e4f85606981ce 100644 --- a/src/Symfony/Component/Templating/PhpEngine.php +++ b/src/Symfony/Component/Templating/PhpEngine.php @@ -173,6 +173,7 @@ protected function evaluate(Storage $template, array $parameters = []) * * @throws \InvalidArgumentException if the helper is not defined */ + #[\ReturnTypeWillChange] public function offsetGet($name) { return $this->get($name); @@ -185,6 +186,7 @@ public function offsetGet($name) * * @return bool true if the helper is defined, false otherwise */ + #[\ReturnTypeWillChange] public function offsetExists($name) { return isset($this->helpers[$name]); @@ -198,6 +200,7 @@ public function offsetExists($name) * * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($name, $value) { $this->set($name, $value); @@ -212,6 +215,7 @@ public function offsetSet($name, $value) * * @throws \LogicException */ + #[\ReturnTypeWillChange] public function offsetUnset($name) { throw new \LogicException(sprintf('You can\'t unset a helper (%s).', $name)); diff --git a/src/Symfony/Component/Validator/ConstraintViolationList.php b/src/Symfony/Component/Validator/ConstraintViolationList.php index bd6443fc45889..e057e916ae16f 100644 --- a/src/Symfony/Component/Validator/ConstraintViolationList.php +++ b/src/Symfony/Component/Validator/ConstraintViolationList.php @@ -110,6 +110,7 @@ public function remove($offset) * * @return \ArrayIterator|ConstraintViolationInterface[] */ + #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->violations); @@ -118,6 +119,7 @@ public function getIterator() /** * @return int */ + #[\ReturnTypeWillChange] public function count() { return \count($this->violations); @@ -126,6 +128,7 @@ public function count() /** * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($offset) { return $this->has($offset); @@ -136,6 +139,7 @@ public function offsetExists($offset) * * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->get($offset); @@ -146,6 +150,7 @@ public function offsetGet($offset) * * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($offset, $violation) { if (null === $offset) { @@ -160,6 +165,7 @@ public function offsetSet($offset, $violation) * * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($offset) { $this->remove($offset); diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php b/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php index 34b208b2bea0c..f248576d2f2e5 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php @@ -29,12 +29,17 @@ public function offsetExists($offset): bool return \array_key_exists($offset, $this->array); } + /** + * @param mixed $offset + * @return mixed + */ + #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->array[$offset]; } - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { if (null === $offset) { $this->array[] = $value; @@ -43,7 +48,7 @@ public function offsetSet($offset, $value) } } - public function offsetUnset($offset) + public function offsetUnset($offset): void { unset($this->array[$offset]); } diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 114bf50e5b038..8f621b12a7627 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -111,6 +111,7 @@ public function getValue($recursive = false) /** * @return int */ + #[\ReturnTypeWillChange] public function count() { return \count($this->getValue()); @@ -119,6 +120,7 @@ public function count() /** * @return \Traversable */ + #[\ReturnTypeWillChange] public function getIterator() { if (!\is_array($value = $this->getValue())) { @@ -150,6 +152,7 @@ public function __isset($key) /** * @return bool */ + #[\ReturnTypeWillChange] public function offsetExists($key) { return $this->__isset($key); @@ -158,6 +161,7 @@ public function offsetExists($key) /** * @return mixed */ + #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->__get($key); @@ -166,6 +170,7 @@ public function offsetGet($key) /** * @return void */ + #[\ReturnTypeWillChange] public function offsetSet($key, $value) { throw new \BadMethodCallException(self::class.' objects are immutable.'); @@ -174,6 +179,7 @@ public function offsetSet($key, $value) /** * @return void */ + #[\ReturnTypeWillChange] public function offsetUnset($key) { throw new \BadMethodCallException(self::class.' objects are immutable.'); From 6d0e144365200c24231f5ccee06a2bef81e9d3aa Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Thu, 5 Aug 2021 00:42:04 +0200 Subject: [PATCH 11/50] Fix test Signed-off-by: Alexander M. Turek <me@derrabus.de> --- src/Symfony/Component/VarExporter/Tests/VarExporterTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php index 852e30c393885..cd10c7af37a8a 100644 --- a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php +++ b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php @@ -313,7 +313,7 @@ public function __construct(array $array) parent::__construct($array, 1); } - public function setFlags($flags) + public function setFlags($flags): void { throw new \BadMethodCallException('Calling MyArrayObject::setFlags() is forbidden'); } @@ -341,12 +341,12 @@ public function __construct(bool $throw = true) final class FinalArrayIterator extends \ArrayIterator { - public function serialize() + public function serialize(): string { return serialize([123, parent::serialize()]); } - public function unserialize($data) + public function unserialize($data): void { if ('' === $data) { throw new \InvalidArgumentException('Serialized data is empty.'); From af37c646b5bb7f9562bc2a5d4634811d3d3f109c Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Thu, 5 Aug 2021 07:31:49 +0200 Subject: [PATCH 12/50] Fix broken mock Signed-off-by: Alexander M. Turek <me@derrabus.de> --- .../Storage/Proxy/SessionHandlerProxyTest.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php index 1422eccfbc049..972a2745132e1 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php @@ -103,17 +103,21 @@ public function testRead() public function testWrite() { $this->mock->expects($this->once()) - ->method('write'); + ->method('write') + ->willReturn(true) + ; - $this->proxy->write('id', 'data'); + $this->assertTrue($this->proxy->write('id', 'data')); } public function testDestroy() { $this->mock->expects($this->once()) - ->method('destroy'); + ->method('destroy') + ->willReturn(true) + ; - $this->proxy->destroy('id'); + $this->assertTrue($this->proxy->destroy('id')); } public function testGc() @@ -149,7 +153,9 @@ public function testUpdateTimestamp() $proxy->updateTimestamp('id', 'data'); $this->mock->expects($this->once()) - ->method('write'); + ->method('write') + ->willReturn(true) + ; $this->proxy->updateTimestamp('id', 'data'); } From 0a46d3793d0190cfdc418d1ca8b529c71f191728 Mon Sep 17 00:00:00 2001 From: Tomas <norkunas.tom@gmail.com> Date: Thu, 5 Aug 2021 13:47:43 +0300 Subject: [PATCH 13/50] Fix ExecutionContextInterface::setParameter phpdoc example --- .../Component/Validator/Context/ExecutionContextInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php b/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php index 14f7617e43fb2..f23182e473fbe 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php @@ -76,8 +76,8 @@ public function addViolation($message, array $params = []); * add the violation when you're done with the configuration: * * $context->buildViolation('Please enter a number between %min% and %max%.') - * ->setParameter('%min%', 3) - * ->setParameter('%max%', 10) + * ->setParameter('%min%', '3') + * ->setParameter('%max%', '10') * ->setTranslationDomain('number_validation') * ->addViolation(); * From b43da3a714da28d79dabb61a8a1e9a3f747e26aa Mon Sep 17 00:00:00 2001 From: Fabien Salathe <fabacrans@gmail.com> Date: Mon, 26 Jul 2021 17:08:08 +0200 Subject: [PATCH 14/50] [FrameworkBundle] Update cache:clear help --- .../Bundle/FrameworkBundle/Command/CacheClearCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 908858019b371..d112c9b086c0f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -59,7 +59,7 @@ protected function configure() ]) ->setDescription('Clear the cache') ->setHelp(<<<'EOF' -The <info>%command.name%</info> command clears the application cache for a given environment +The <info>%command.name%</info> command clears and warms up the application cache for a given environment and debug mode: <info>php %command.full_name% --env=dev</info> From 2f742bc25ffa082e46138fe8b1efa9621991ce1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Ols=CC=8Cavsky=CC=81?= <molsavsky1@gmail.com> Date: Wed, 4 Aug 2021 10:56:59 +0200 Subject: [PATCH 15/50] Do not add namespace argument to NullAdapter in CachePoolPass --- .../DependencyInjection/CachePoolPass.php | 5 +++-- .../DependencyInjection/CachePoolPassTest.php | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php b/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php index f52d0271e4117..c707ad9a28793 100644 --- a/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php +++ b/src/Symfony/Component/Cache/DependencyInjection/CachePoolPass.php @@ -14,6 +14,7 @@ use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\Cache\Adapter\NullAdapter; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -130,7 +131,7 @@ public function process(ContainerBuilder $container) $chainedPool->replaceArgument($i++, new Reference(static::getServiceProvider($container, $chainedTags[0]['provider']))); } - if (isset($tags[0]['namespace']) && ArrayAdapter::class !== $adapter->getClass()) { + if (isset($tags[0]['namespace']) && !\in_array($adapter->getClass(), [ArrayAdapter::class, NullAdapter::class], true)) { $chainedPool->replaceArgument($i++, $tags[0]['namespace']); } @@ -155,7 +156,7 @@ public function process(ContainerBuilder $container) if ($tags[0][$attr]) { $pool->addTag($this->kernelResetTag, ['method' => $tags[0][$attr]]); } - } elseif ('namespace' !== $attr || ArrayAdapter::class !== $class) { + } elseif ('namespace' !== $attr || !\in_array($class, [ArrayAdapter::class, NullAdapter::class], true)) { $pool->replaceArgument($i++, $tags[0][$attr]); } unset($tags[0][$attr]); diff --git a/src/Symfony/Component/Cache/Tests/DependencyInjection/CachePoolPassTest.php b/src/Symfony/Component/Cache/Tests/DependencyInjection/CachePoolPassTest.php index 9769b3992e88f..a77df6b1ec9ad 100644 --- a/src/Symfony/Component/Cache/Tests/DependencyInjection/CachePoolPassTest.php +++ b/src/Symfony/Component/Cache/Tests/DependencyInjection/CachePoolPassTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Cache\Adapter\ApcuAdapter; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\Cache\Adapter\NullAdapter; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\Cache\DependencyInjection\CachePoolPass; use Symfony\Component\DependencyInjection\ChildDefinition; @@ -116,6 +117,23 @@ public function testNamespaceArgumentIsNotReplacedIfArrayAdapterIsUsed() $this->assertCount(0, $container->getDefinition('app.cache_pool')->getArguments()); } + public function testNamespaceArgumentIsNotReplacedIfNullAdapterIsUsed() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.container_class', 'app'); + $container->setParameter('kernel.project_dir', 'foo'); + + $container->register('cache.adapter.null', NullAdapter::class); + + $cachePool = new ChildDefinition('cache.adapter.null'); + $cachePool->addTag('cache.pool'); + $container->setDefinition('app.cache_pool', $cachePool); + + $this->cachePoolPass->process($container); + + $this->assertCount(0, $container->getDefinition('app.cache_pool')->getArguments()); + } + public function testArgsAreReplaced() { $container = new ContainerBuilder(); From 2982eec5f12500926c02e0ca882af6cd486a6e18 Mon Sep 17 00:00:00 2001 From: Richard van Laak <rvanlaak@gmail.com> Date: Tue, 20 Jul 2021 12:33:05 +0200 Subject: [PATCH 16/50] Report mismatches between trans-unit id and source text via status script --- .github/workflows/integration-tests.yml | 10 ++ .../Resources/bin/translation-status.php | 93 ++++++++++++++++--- 2 files changed, 90 insertions(+), 13 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 4074f78d39356..9832c8a9d09a2 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -117,3 +117,13 @@ jobs: # docker run --rm -e COMPOSER_ROOT_VERSION -v $(pwd):/app -v $(which composer):/usr/local/bin/composer -v $(which vulcain):/usr/local/bin/vulcain -w /app php:8.0-alpine ./phpunit src/Symfony/Component/HttpClient/Tests/CurlHttpClientTest.php --filter testHttp2Push # sudo rm -rf .phpunit # [ -d .phpunit.bak ] && mv .phpunit.bak .phpunit + + - uses: marceloprado/has-changed-path@v1 + id: changed-translation-files + with: + paths: src/**/Resources/translations/*.xlf + + - name: Check Translation Status + if: steps.changed-translation-files.outputs.changed == 'true' + run: | + php src/Symfony/Component/Translation/Resources/bin/translation-status.php -v diff --git a/src/Symfony/Component/Translation/Resources/bin/translation-status.php b/src/Symfony/Component/Translation/Resources/bin/translation-status.php index 4e0723bb40615..a769164273a6a 100644 --- a/src/Symfony/Component/Translation/Resources/bin/translation-status.php +++ b/src/Symfony/Component/Translation/Resources/bin/translation-status.php @@ -19,13 +19,16 @@ # show the translation status of all locales $ php translation-status.php - # show the translation status of all locales and all their missing translations + # only show the translation status of incomplete or erroneous locales + $ php translation-status.php --incomplete + + # show the translation status of all locales, all their missing translations and mismatches between trans-unit id and source $ php translation-status.php -v # show the status of a single locale $ php translation-status.php fr - # show the status of a single locale and all its missing translations + # show the status of a single locale, missing translations and mismatches between trans-unit id and source $ php translation-status.php fr -v END; @@ -35,6 +38,8 @@ 'verbose_output' => false, // NULL = analyze all locales 'locale_to_analyze' => null, + // append --incomplete to only show incomplete languages + 'include_completed_languages' => true, // the reference files all the other translations are compared to 'original_files' => [ 'src/Symfony/Component/Form/Resources/translations/validators.en.xlf', @@ -46,12 +51,17 @@ $argc = $_SERVER['argc']; $argv = $_SERVER['argv']; -if ($argc > 3) { +if ($argc > 4) { echo str_replace('translation-status.php', $argv[0], $usageInstructions); exit(1); } foreach (array_slice($argv, 1) as $argumentOrOption) { + if ('--incomplete' === $argumentOrOption) { + $config['include_completed_languages'] = false; + continue; + } + if (str_starts_with($argumentOrOption, '-')) { $config['verbose_output'] = true; } else { @@ -67,6 +77,7 @@ } $totalMissingTranslations = 0; +$totalTranslationMismatches = 0; foreach ($config['original_files'] as $originalFilePath) { $translationFilePaths = findTranslationFiles($originalFilePath, $config['locale_to_analyze']); @@ -75,11 +86,14 @@ $totalMissingTranslations += array_sum(array_map(function ($translation) { return count($translation['missingKeys']); }, array_values($translationStatus))); + $totalTranslationMismatches += array_sum(array_map(function ($translation) { + return count($translation['mismatches']); + }, array_values($translationStatus))); - printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output']); + printTranslationStatus($originalFilePath, $translationStatus, $config['verbose_output'], $config['include_completed_languages']); } -exit($totalMissingTranslations > 0 ? 1 : 0); +exit($totalTranslationMismatches > 0 ? 1 : 0); function findTranslationFiles($originalFilePath, $localeToAnalyze) { @@ -112,21 +126,29 @@ function calculateTranslationStatus($originalFilePath, $translationFilePaths) foreach ($translationFilePaths as $locale => $translationPath) { $translatedKeys = extractTranslationKeys($translationPath); $missingKeys = array_diff_key($allTranslationKeys, $translatedKeys); + $mismatches = findTransUnitMismatches($allTranslationKeys, $translatedKeys); $translationStatus[$locale] = [ 'total' => count($allTranslationKeys), 'translated' => count($translatedKeys), 'missingKeys' => $missingKeys, + 'mismatches' => $mismatches, ]; + $translationStatus[$locale]['is_completed'] = isTranslationCompleted($translationStatus[$locale]); } return $translationStatus; } -function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput) +function isTranslationCompleted(array $translationStatus): bool +{ + return $translationStatus['total'] === $translationStatus['translated'] && 0 === count($translationStatus['mismatches']); +} + +function printTranslationStatus($originalFilePath, $translationStatus, $verboseOutput, $includeCompletedLanguages) { printTitle($originalFilePath); - printTable($translationStatus, $verboseOutput); + printTable($translationStatus, $verboseOutput, $includeCompletedLanguages); echo \PHP_EOL.\PHP_EOL; } @@ -152,13 +174,35 @@ function extractTranslationKeys($filePath) return $translationKeys; } +/** + * Check whether the trans-unit id and source match with the base translation. + */ +function findTransUnitMismatches(array $baseTranslationKeys, array $translatedKeys): array +{ + $mismatches = []; + + foreach ($baseTranslationKeys as $translationId => $translationKey) { + if (!isset($translatedKeys[$translationId])) { + continue; + } + if ($translatedKeys[$translationId] !== $translationKey) { + $mismatches[$translationId] = [ + 'found' => $translatedKeys[$translationId], + 'expected' => $translationKey, + ]; + } + } + + return $mismatches; +} + function printTitle($title) { echo $title.\PHP_EOL; echo str_repeat('=', strlen($title)).\PHP_EOL.\PHP_EOL; } -function printTable($translations, $verboseOutput) +function printTable($translations, $verboseOutput, bool $includeCompletedLanguages) { if (0 === count($translations)) { echo 'No translations found'; @@ -168,24 +212,47 @@ function printTable($translations, $verboseOutput) $longestLocaleNameLength = max(array_map('strlen', array_keys($translations))); foreach ($translations as $locale => $translation) { + if (!$includeCompletedLanguages && $translation['is_completed']) { + continue; + } + if ($translation['translated'] > $translation['total']) { textColorRed(); - } elseif ($translation['translated'] === $translation['total']) { + } elseif (count($translation['mismatches']) > 0) { + textColorRed(); + } elseif ($translation['is_completed']) { textColorGreen(); } - echo sprintf('| Locale: %-'.$longestLocaleNameLength.'s | Translated: %d/%d', $locale, $translation['translated'], $translation['total']).\PHP_EOL; + echo sprintf( + '| Locale: %-'.$longestLocaleNameLength.'s | Translated: %2d/%2d | Mismatches: %d |', + $locale, + $translation['translated'], + $translation['total'], + count($translation['mismatches']) + ).\PHP_EOL; textColorNormal(); + $shouldBeClosed = false; if (true === $verboseOutput && count($translation['missingKeys']) > 0) { - echo str_repeat('-', 80).\PHP_EOL; - echo '| Missing Translations:'.\PHP_EOL; + echo '| Missing Translations:'.\PHP_EOL; foreach ($translation['missingKeys'] as $id => $content) { - echo sprintf('| (id=%s) %s', $id, $content).\PHP_EOL; + echo sprintf('| (id=%s) %s', $id, $content).\PHP_EOL; } + $shouldBeClosed = true; + } + if (true === $verboseOutput && count($translation['mismatches']) > 0) { + echo '| Mismatches between trans-unit id and source:'.\PHP_EOL; + foreach ($translation['mismatches'] as $id => $content) { + echo sprintf('| (id=%s) Expected: %s', $id, $content['expected']).\PHP_EOL; + echo sprintf('| Found: %s', $content['found']).\PHP_EOL; + } + $shouldBeClosed = true; + } + if ($shouldBeClosed) { echo str_repeat('-', 80).\PHP_EOL; } } From b9341b7d44617e493455a6f21dad84357ce9cdb1 Mon Sep 17 00:00:00 2001 From: Wahyu Kristianto <w.kristories@gmail.com> Date: Sun, 8 Aug 2021 11:32:25 +0700 Subject: [PATCH 17/50] [Security][Validator] Add missing translations for Indonesian (id) --- .../Core/Resources/translations/security.id.xlf | 12 ++++++++++-- .../Resources/translations/validators.id.xlf | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf index 91315bdf1d016..119e2d0cd70fb 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf @@ -64,11 +64,19 @@ </trans-unit> <trans-unit id="17"> <source>Too many failed login attempts, please try again later.</source> - <target>Terlalu banyak percobaan login yang salah, Silahkan coba lagi nanti.</target> + <target>Terlalu banyak percobaan login yang salah, silahkan coba lagi nanti.</target> </trans-unit> <trans-unit id="18"> <source>Invalid or expired login link.</source> - <target>Link login salah atau sudah kadaluwarsa.</target> + <target>Link login salah atau sudah kedaluwarsa.</target> + </trans-unit> + <trans-unit id="19"> + <source>Too many failed login attempts, please try again in %minutes% minute.</source> + <target>Terlalu banyak percobaan login yang salah, silahkan coba lagi dalam %minutes% menit.</target> + </trans-unit> + <trans-unit id="20"> + <source>Too many failed login attempts, please try again in %minutes% minutes.</source> + <target>Terlalu banyak percobaan login yang salah, silahkan coba lagi dalam %minutes% menit.</target> </trans-unit> </body> </file> diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf index 40d07cf57cbb9..4793a16f32032 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.id.xlf @@ -386,6 +386,10 @@ <source>This value is not a valid International Securities Identification Number (ISIN).</source> <target>Nilai ini bukan merupakan International Securities Identification Number (ISIN) yang sah.</target> </trans-unit> + <trans-unit id="100"> + <source>This value should be a valid expression.</source> + <target>Nilai ini harus berupa ekspresi yang valid.</target> + </trans-unit> </body> </file> </xliff> From 50bcb220d92ce8c368a46df55011580ee4928bb1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Mon, 9 Aug 2021 10:09:12 +0200 Subject: [PATCH 18/50] cs fix --- src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php | 1 + .../Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php | 1 + .../PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php | 1 + .../Component/Validator/Tests/Fixtures/CustomArrayObject.php | 1 + 4 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php b/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php index 41cb5af4cdf7b..942add40e3736 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/CustomArrayObject.php @@ -31,6 +31,7 @@ public function offsetExists($offset): bool /** * @param mixed $offset + * * @return mixed */ #[\ReturnTypeWillChange] diff --git a/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php b/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php index 2679948b14733..803e5561f6573 100644 --- a/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php +++ b/src/Symfony/Component/Intl/Data/Util/ArrayAccessibleResourceBundle.php @@ -46,6 +46,7 @@ public function offsetExists($offset): bool /** * @param mixed $offset + * * @return mixed */ #[\ReturnTypeWillChange] diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php index da8911ed7207f..72e053171c841 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/NonTraversableArrayObject.php @@ -31,6 +31,7 @@ public function offsetExists($offset): bool /** * @param mixed $offset + * * @return mixed */ #[\ReturnTypeWillChange] diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php b/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php index f248576d2f2e5..4ca7f4a99fabe 100644 --- a/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php +++ b/src/Symfony/Component/Validator/Tests/Fixtures/CustomArrayObject.php @@ -31,6 +31,7 @@ public function offsetExists($offset): bool /** * @param mixed $offset + * * @return mixed */ #[\ReturnTypeWillChange] From 0f5125364e3f76be1c016b59bd9fbc7cf1f9d65c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Mon, 9 Aug 2021 14:05:14 +0200 Subject: [PATCH 19/50] cs fix --- .../PropertyAccess/Tests/Fixtures/TraversableArrayObject.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php index 26ab98575f25f..eb4da3f201342 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TraversableArrayObject.php @@ -31,6 +31,7 @@ public function offsetExists($offset): bool /** * @param mixed $offset + * * @return mixed */ #[\ReturnTypeWillChange] From c5cbc0d1ac228d30744d23254a1e1eb3a59f0cc0 Mon Sep 17 00:00:00 2001 From: Marco Petersen <m@rcopetersen.com> Date: Tue, 10 Aug 2021 21:52:50 +0200 Subject: [PATCH 20/50] Update Tagalog translations --- .../Security/Core/Resources/translations/security.tl.xlf | 8 ++++++++ .../Validator/Resources/translations/validators.tl.xlf | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf index 5bf5304b5cae1..66547b2a3d1be 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.tl.xlf @@ -70,6 +70,14 @@ <source>Invalid or expired login link.</source> <target>Inbalido o nagexpire na ang link para makapaglogin.</target> </trans-unit> + <trans-unit id="19"> + <source>Too many failed login attempts, please try again in %minutes% minute.</source> + <target>Madaming bagsak na pagtatangka, pakisubukan ulit pagkatapos ng %minutes% minuto.</target> + </trans-unit> + <trans-unit id="20"> + <source>Too many failed login attempts, please try again in %minutes% minute.</source> + <target>Madaming bagsak na pagtatangka, pakisubukan ulit pagkatapos ng %minutes% minuto.</target> + </trans-unit> </body> </file> </xliff> diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf index e930e59014191..90fe83bb31cb9 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tl.xlf @@ -386,6 +386,10 @@ <source>This value is not a valid International Securities Identification Number (ISIN).</source> <target>Ang halagang ito ay hindi wastong International Securities Identification Number (ISIN).</target> </trans-unit> + <trans-unit id="100"> + <source>This value should be a valid expression.</source> + <target>Ang halagang ito ay dapat wastong ekspresyon.</target> + </trans-unit> </body> </file> </xliff> From 2bfeb5db7e2c33a1491349531b7b90a68906f2e0 Mon Sep 17 00:00:00 2001 From: Hendrik Luup <hendrik.luup@we.ee> Date: Wed, 11 Aug 2021 17:07:37 +0300 Subject: [PATCH 21/50] Add Estonian (et) translations --- .../Resources/translations/validators.et.xlf | 120 ++++++++++++++++++ .../Resources/translations/security.et.xlf | 83 ++++++++++++ .../Resources/translations/validators.et.xlf | 38 +++++- 3 files changed, 234 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Component/Security/Core/Resources/translations/security.et.xlf diff --git a/src/Symfony/Component/Form/Resources/translations/validators.et.xlf b/src/Symfony/Component/Form/Resources/translations/validators.et.xlf index 1a9867fa20953..6524c86b144ee 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.et.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.et.xlf @@ -14,6 +14,126 @@ <source>The CSRF token is invalid. Please try to resubmit the form.</source> <target>CSRF-märgis on vigane. Palun proovi vormi uuesti esitada.</target> </trans-unit> + <trans-unit id="99"> + <source>This value is not a valid HTML5 color.</source> + <target>See väärtus ei ole korrektne HTML5 värv.</target> + </trans-unit> + <trans-unit id="100"> + <source>Please enter a valid birthdate.</source> + <target>Palun sisesta korrektne sünnikuupäev.</target> + </trans-unit> + <trans-unit id="101"> + <source>The selected choice is invalid.</source> + <target>Tehtud valik on vigane.</target> + </trans-unit> + <trans-unit id="102"> + <source>The collection is invalid.</source> + <target>Kogum on vigane.</target> + </trans-unit> + <trans-unit id="103"> + <source>Please select a valid color.</source> + <target>Palun vali korrektne värv.</target> + </trans-unit> + <trans-unit id="104"> + <source>Please select a valid country.</source> + <target>Palun vali korrektne riik.</target> + </trans-unit> + <trans-unit id="105"> + <source>Please select a valid currency.</source> + <target>Palun vali korrektne valuuta.</target> + </trans-unit> + <trans-unit id="106"> + <source>Please choose a valid date interval.</source> + <target>Palun vali korrektne kuupäevade vahemik.</target> + </trans-unit> + <trans-unit id="107"> + <source>Please enter a valid date and time.</source> + <target>Palun sisesta korrektne kuupäev ja kellaaeg.</target> + </trans-unit> + <trans-unit id="108"> + <source>Please enter a valid date.</source> + <target>Palun sisesta korrektne kuupäev.</target> + </trans-unit> + <trans-unit id="109"> + <source>Please select a valid file.</source> + <target>Palun vali korrektne fail.</target> + </trans-unit> + <trans-unit id="110"> + <source>The hidden field is invalid.</source> + <target>Peidetud väli on vigane.</target> + </trans-unit> + <trans-unit id="111"> + <source>Please enter an integer.</source> + <target>Palun sisesta täisarv.</target> + </trans-unit> + <trans-unit id="112"> + <source>Please select a valid language.</source> + <target>Palun vali korrektne keel.</target> + </trans-unit> + <trans-unit id="113"> + <source>Please select a valid locale.</source> + <target>Palun vali korrektne keelekood.</target> + </trans-unit> + <trans-unit id="114"> + <source>Please enter a valid money amount.</source> + <target>Palun sisesta korrektne rahaline väärtus.</target> + </trans-unit> + <trans-unit id="115"> + <source>Please enter a number.</source> + <target>Palun sisesta number.</target> + </trans-unit> + <trans-unit id="116"> + <source>The password is invalid.</source> + <target>Vigane parool.</target> + </trans-unit> + <trans-unit id="117"> + <source>Please enter a percentage value.</source> + <target>Palun sisesta protsendiline väärtus.</target> + </trans-unit> + <trans-unit id="118"> + <source>The values do not match.</source> + <target>Väärtused ei klapi.</target> + </trans-unit> + <trans-unit id="119"> + <source>Please enter a valid time.</source> + <target>Palun sisesta korrektne aeg.</target> + </trans-unit> + <trans-unit id="120"> + <source>Please select a valid timezone.</source> + <target>Palun vali korrektne ajavöönd.</target> + </trans-unit> + <trans-unit id="121"> + <source>Please enter a valid URL.</source> + <target>Palun sisesta korrektne URL.</target> + </trans-unit> + <trans-unit id="122"> + <source>Please enter a valid search term.</source> + <target>Palun sisesta korrektne otsingutermin.</target> + </trans-unit> + <trans-unit id="123"> + <source>Please provide a valid phone number.</source> + <target>Palun sisesta korrektne telefoninumber.</target> + </trans-unit> + <trans-unit id="124"> + <source>The checkbox has an invalid value.</source> + <target>Märkeruudu väärtus on vigane.</target> + </trans-unit> + <trans-unit id="125"> + <source>Please enter a valid email address.</source> + <target>Palun sisesta korrektne e-posti aadress.</target> + </trans-unit> + <trans-unit id="126"> + <source>Please select a valid option.</source> + <target>Palun tee korrektne valik.</target> + </trans-unit> + <trans-unit id="127"> + <source>Please select a valid range.</source> + <target>Palun vali korrektne vahemik.</target> + </trans-unit> + <trans-unit id="128"> + <source>Please enter a valid week.</source> + <target>Palun sisesta korrektne nädal.</target> + </trans-unit> </body> </file> </xliff> diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.et.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.et.xlf new file mode 100644 index 0000000000000..cc2b16ae853dc --- /dev/null +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.et.xlf @@ -0,0 +1,83 @@ +<?xml version="1.0"?> +<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> + <file source-language="en" datatype="plaintext" original="file.ext"> + <body> + <trans-unit id="1"> + <source>An authentication exception occurred.</source> + <target>Autentimisel juhtus ootamatu viga.</target> + </trans-unit> + <trans-unit id="2"> + <source>Authentication credentials could not be found.</source> + <target>Autentimisandmeid ei leitud.</target> + </trans-unit> + <trans-unit id="3"> + <source>Authentication request could not be processed due to a system problem.</source> + <target>Autentimispäring ei õnnestunud süsteemi probleemi tõttu.</target> + </trans-unit> + <trans-unit id="4"> + <source>Invalid credentials.</source> + <target>Vigased autentimisandmed.</target> + </trans-unit> + <trans-unit id="5"> + <source>Cookie has already been used by someone else.</source> + <target>Küpsis on juba kellegi teise poolt kasutuses.</target> + </trans-unit> + <trans-unit id="6"> + <source>Not privileged to request the resource.</source> + <target>Ressursi pärimiseks pole piisavalt õiguseid.</target> + </trans-unit> + <trans-unit id="7"> + <source>Invalid CSRF token.</source> + <target>Vigane CSRF märgis.</target> + </trans-unit> + <trans-unit id="9"> + <source>No authentication provider found to support the authentication token.</source> + <target>Ei leitud sobivat autentimismeetodit, mis toetaks autentimismärgist.</target> + </trans-unit> + <trans-unit id="10"> + <source>No session available, it either timed out or cookies are not enabled.</source> + <target>Seanss puudub, see on kas aegunud või pole küpsised lubatud.</target> + </trans-unit> + <trans-unit id="11"> + <source>No token could be found.</source> + <target>Identsustõendit ei leitud.</target> + </trans-unit> + <trans-unit id="12"> + <source>Username could not be found.</source> + <target>Kasutajanime ei leitud.</target> + </trans-unit> + <trans-unit id="13"> + <source>Account has expired.</source> + <target>Kasutajakonto on aegunud.</target> + </trans-unit> + <trans-unit id="14"> + <source>Credentials have expired.</source> + <target>Autentimistunnused on aegunud.</target> + </trans-unit> + <trans-unit id="15"> + <source>Account is disabled.</source> + <target>Kasutajakonto on keelatud.</target> + </trans-unit> + <trans-unit id="16"> + <source>Account is locked.</source> + <target>Kasutajakonto on lukustatud.</target> + </trans-unit> + <trans-unit id="17"> + <source>Too many failed login attempts, please try again later.</source> + <target>Liiga palju ebaõnnestunud autentimise katseid, palun proovi hiljem uuesti.</target> + </trans-unit> + <trans-unit id="18"> + <source>Invalid or expired login link.</source> + <target>Vigane või aegunud sisselogimise link.</target> + </trans-unit> + <trans-unit id="19"> + <source>Too many failed login attempts, please try again in %minutes% minute.</source> + <target>Liiga palju ebaõnnestunud autentimise katseid, palun proovi uuesti %minutes% minuti pärast.</target> + </trans-unit> + <trans-unit id="20"> + <source>Too many failed login attempts, please try again in %minutes% minutes.</source> + <target>Liiga palju ebaõnnestunud autentimise katseid, palun proovi uuesti %minutes% minuti pärast.</target> + </trans-unit> + </body> + </file> +</xliff> diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf index 261b8f34e62f9..930b47f82e95a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.et.xlf @@ -32,11 +32,11 @@ </trans-unit> <trans-unit id="8"> <source>One or more of the given values is invalid.</source> - <target>One or more of the given values is invalid.</target> + <target>Üks või rohkem väärtustest on vigane.</target> </trans-unit> <trans-unit id="9"> <source>This field was not expected.</source> - <target>See väli ei oodatud.</target> + <target>See väli ei olnud oodatud.</target> </trans-unit> <trans-unit id="10"> <source>This field is missing.</source> @@ -179,7 +179,7 @@ <target>Väärtus peaks olema kasutaja kehtiv salasõna.</target> </trans-unit> <trans-unit id="48"> - <source>This value should have exactly {{ limit }} characters.</source> + <source>This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.</source> <target>Väärtus peaks olema täpselt {{ limit }} tähemärk pikk.|Väärtus peaks olema täpselt {{ limit }} tähemärki pikk.</target> </trans-unit> <trans-unit id="49"> @@ -203,15 +203,15 @@ <target>PHP laiendi tõttu ebaõnnestus faili üleslaadimine.</target> </trans-unit> <trans-unit id="54"> - <source>This collection should contain {{ limit }} elements or more.</source> + <source>This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more.</source> <target>Kogumikus peaks olema vähemalt {{ limit }} element.|Kogumikus peaks olema vähemalt {{ limit }} elementi.</target> </trans-unit> <trans-unit id="55"> - <source>This collection should contain {{ limit }} elements or less.</source> + <source>This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less.</source> <target>Kogumikus peaks olema ülimalt {{ limit }} element.|Kogumikus peaks olema ülimalt {{ limit }} elementi.</target> </trans-unit> <trans-unit id="56"> - <source>This collection should contain exactly {{ limit }} elements.</source> + <source>This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements.</source> <target>Kogumikus peaks olema täpselt {{ limit }} element.|Kogumikus peaks olema täpselt {{ limit }}|elementi.</target> </trans-unit> <trans-unit id="57"> @@ -304,7 +304,7 @@ </trans-unit> <trans-unit id="79"> <source>The host could not be resolved.</source> - <target>Peremeest ei õnnestunud lahendada.</target> + <target>Sellist domeeni ei õnnestunud leida.</target> </trans-unit> <trans-unit id="80"> <source>This value does not match the expected {{ charset }} charset.</source> @@ -366,6 +366,30 @@ <source>This value should be between {{ min }} and {{ max }}.</source> <target>See väärtus peaks olema vahemikus {{ min }} kuni {{ max }}.</target> </trans-unit> + <trans-unit id="95"> + <source>This value is not a valid hostname.</source> + <target>See väärtus pole korrektne domeeninimi.</target> + </trans-unit> + <trans-unit id="96"> + <source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source> + <target>Selles kogus olevate elementide arv peab olema arvu {{ compared_value }} kordne.</target> + </trans-unit> + <trans-unit id="97"> + <source>This value should satisfy at least one of the following constraints:</source> + <target>See väärtus peab vastama vähemalt ühele järgmistest tingimustest:</target> + </trans-unit> + <trans-unit id="98"> + <source>Each element of this collection should satisfy its own set of constraints.</source> + <target>Kõik väärtused selles kogus peavad vastama oma tingimustele.</target> + </trans-unit> + <trans-unit id="99"> + <source>This value is not a valid International Securities Identification Number (ISIN).</source> + <target>See väärtus pole korrektne ISIN-kood.</target> + </trans-unit> + <trans-unit id="100"> + <source>This value should be a valid expression.</source> + <target>See väärtus pole korrektne avaldis.</target> + </trans-unit> </body> </file> </xliff> From 94d843f7669207445ba5f694858c324d9cc4090c Mon Sep 17 00:00:00 2001 From: Hendrik Luup <hendrik.luup@we.ee> Date: Fri, 13 Aug 2021 17:07:59 +0300 Subject: [PATCH 22/50] Do not use str_start_with We are not loading polyfill here so str_starts_with is not available PHP <8.0 --- .../Component/Translation/Resources/bin/translation-status.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/Resources/bin/translation-status.php b/src/Symfony/Component/Translation/Resources/bin/translation-status.php index a769164273a6a..fac8acbadca32 100644 --- a/src/Symfony/Component/Translation/Resources/bin/translation-status.php +++ b/src/Symfony/Component/Translation/Resources/bin/translation-status.php @@ -62,7 +62,7 @@ continue; } - if (str_starts_with($argumentOrOption, '-')) { + if (0 === strpos($argumentOrOption, '-')) { $config['verbose_output'] = true; } else { $config['locale_to_analyze'] = $argumentOrOption; From f75f7582843f28e23deff97d37091a9562199bcf Mon Sep 17 00:00:00 2001 From: Wouter de Jong <wouter@wouterj.nl> Date: Mon, 16 Aug 2021 21:37:05 +0200 Subject: [PATCH 23/50] Show nice CLI output in Psalm action --- .github/workflows/psalm.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml index a9adb8e7cf532..9c126e2ef2422 100644 --- a/.github/workflows/psalm.yml +++ b/.github/workflows/psalm.yml @@ -52,4 +52,5 @@ jobs: - name: Psalm run: | + ./vendor/bin/psalm.phar --no-progress ./vendor/bin/psalm.phar --output-format=github --no-progress From 25dac25d079899152dcbfa87a8c9d43552a7c353 Mon Sep 17 00:00:00 2001 From: Brad Jones <brad@bradjonesllc.com> Date: Tue, 17 Aug 2021 23:34:26 -0600 Subject: [PATCH 24/50] Update NativeSessionStorage docblock to match defaults Symfony overrides a number of PHP's default session INI values, including `use_strict_mode`. This was enabled by default in the HTTP framework bundle in 3.4 https://github.com/symfony/symfony/blob/8ac480a5eaa31595ca4f7c3e29106e9d4ba45527/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md#340 but the docblock was not updated to correspond with this change. --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 97975dba92b4f..916961f5eed5c 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -86,7 +86,7 @@ class NativeSessionStorage implements SessionStorageInterface * name, "PHPSESSID" * referer_check, "" * serialize_handler, "php" - * use_strict_mode, "0" + * use_strict_mode, "1" * use_cookies, "1" * use_only_cookies, "1" * use_trans_sid, "0" From 69904582ba67071166836426c920eb428c79b0aa Mon Sep 17 00:00:00 2001 From: Martin Herndl <martin@herndl.org> Date: Wed, 18 Aug 2021 10:29:30 +0200 Subject: [PATCH 25/50] [HttpKernel] Fix SplFileInfo mock in HttpKernelBrowserTest --- .../Component/HttpKernel/Tests/HttpKernelBrowserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php index 7cd4d52d39650..b32a8955f7372 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php @@ -157,7 +157,7 @@ public function testUploadedFileWhenSizeExceedsUploadMaxFileSize() /* should be modified when the getClientSize will be removed */ $file->expects($this->any()) ->method('getSize') - ->willReturn(\INF) + ->willReturn(\PHP_INT_MAX) ; $file->expects($this->any()) ->method('getClientSize') From 45e0f520570573a7a8569443ed821fbaa14b29e4 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Wed, 18 Aug 2021 11:28:11 +0200 Subject: [PATCH 26/50] Don't produce TypeErrors for non-string CSRF tokens Signed-off-by: Alexander M. Turek <me@derrabus.de> --- .../Security/Http/Firewall/LogoutListener.php | 2 +- .../SimpleFormAuthenticationListener.php | 2 +- ...namePasswordFormAuthenticationListener.php | 2 +- .../Tests/Firewall/LogoutListenerTest.php | 20 +++- ...PasswordFormAuthenticationListenerTest.php | 98 ++++++++++++++++--- 5 files changed, 105 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php index e78f21826f362..83aba4166a6e4 100644 --- a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php @@ -87,7 +87,7 @@ public function authenticate(RequestEvent $event) if (null !== $this->csrfTokenManager) { $csrfToken = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']); - if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) { + if (!\is_string($csrfToken) || false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) { throw new LogoutException('Invalid CSRF token.'); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php index f158d906a4c5f..997e2e7ba04eb 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php @@ -84,7 +84,7 @@ protected function attemptAuthentication(Request $request) if (null !== $this->csrfTokenManager) { $csrfToken = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']); - if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) { + if (!\is_string($csrfToken) || false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) { throw new InvalidCsrfTokenException('Invalid CSRF token.'); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php index b3661eae8afd1..3aaa6dd71a1af 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordFormAuthenticationListener.php @@ -72,7 +72,7 @@ protected function attemptAuthentication(Request $request) if (null !== $this->csrfTokenManager) { $csrfToken = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']); - if (false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) { + if (!\is_string($csrfToken) || false === $this->csrfTokenManager->isTokenValid(new CsrfToken($this->options['csrf_token_id'], $csrfToken))) { throw new InvalidCsrfTokenException('Invalid CSRF token.'); } } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php index 397639fd940f7..4e86dccdd8c39 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/LogoutListenerTest.php @@ -152,7 +152,10 @@ public function testSuccessHandlerReturnsNonResponse() $listener($event); } - public function testCsrfValidationFails() + /** + * @dataProvider provideInvalidCsrfTokens + */ + public function testCsrfValidationFails($invalidToken) { $this->expectException(LogoutException::class); $tokenManager = $this->getTokenManager(); @@ -160,20 +163,31 @@ public function testCsrfValidationFails() [$listener, , $httpUtils, $options] = $this->getListener(null, $tokenManager); $request = new Request(); - $request->query->set('_csrf_token', 'token'); + if (null !== $invalidToken) { + $request->query->set('_csrf_token', $invalidToken); + } $httpUtils->expects($this->once()) ->method('checkRequestPath') ->with($request, $options['logout_path']) ->willReturn(true); - $tokenManager->expects($this->once()) + $tokenManager ->method('isTokenValid') ->willReturn(false); $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST)); } + public function provideInvalidCsrfTokens(): array + { + return [ + ['invalid'], + [['in' => 'valid']], + [null], + ]; + } + private function getTokenManager() { return $this->createMock(CsrfTokenManagerInterface::class); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php index 312014cd1a6f5..e6d9e06d8b698 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordFormAuthenticationListenerTest.php @@ -24,6 +24,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Security; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; @@ -37,7 +38,7 @@ class UsernamePasswordFormAuthenticationListenerTest extends TestCase /** * @dataProvider getUsernameForLength */ - public function testHandleWhenUsernameLength($username, $ok) + public function testHandleWhenUsernameLength(string $username, bool $ok) { $request = Request::create('/login_check', 'POST', ['_username' => $username]); $request->setSession($this->createMock(SessionInterface::class)); @@ -84,10 +85,8 @@ public function testHandleWhenUsernameLength($username, $ok) /** * @dataProvider postOnlyDataProvider */ - public function testHandleNonStringUsernameWithArray($postOnly) + public function testHandleNonStringUsernameWithArray(bool $postOnly) { - $this->expectException(BadRequestHttpException::class); - $this->expectExceptionMessage('The key "_username" must be a string, "array" given.'); $request = Request::create('/login_check', 'POST', ['_username' => []]); $request->setSession($this->createMock(SessionInterface::class)); $listener = new UsernamePasswordFormAuthenticationListener( @@ -101,16 +100,18 @@ public function testHandleNonStringUsernameWithArray($postOnly) ['require_previous_session' => false, 'post_only' => $postOnly] ); $event = new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST); + + $this->expectException(BadRequestHttpException::class); + $this->expectExceptionMessage('The key "_username" must be a string, "array" given.'); + $listener($event); } /** * @dataProvider postOnlyDataProvider */ - public function testHandleNonStringUsernameWithInt($postOnly) + public function testHandleNonStringUsernameWithInt(bool $postOnly) { - $this->expectException(BadRequestHttpException::class); - $this->expectExceptionMessage('The key "_username" must be a string, "integer" given.'); $request = Request::create('/login_check', 'POST', ['_username' => 42]); $request->setSession($this->createMock(SessionInterface::class)); $listener = new UsernamePasswordFormAuthenticationListener( @@ -124,16 +125,18 @@ public function testHandleNonStringUsernameWithInt($postOnly) ['require_previous_session' => false, 'post_only' => $postOnly] ); $event = new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST); + + $this->expectException(BadRequestHttpException::class); + $this->expectExceptionMessage('The key "_username" must be a string, "integer" given.'); + $listener($event); } /** * @dataProvider postOnlyDataProvider */ - public function testHandleNonStringUsernameWithObject($postOnly) + public function testHandleNonStringUsernameWithObject(bool $postOnly) { - $this->expectException(BadRequestHttpException::class); - $this->expectExceptionMessage('The key "_username" must be a string, "object" given.'); $request = Request::create('/login_check', 'POST', ['_username' => new \stdClass()]); $request->setSession($this->createMock(SessionInterface::class)); $listener = new UsernamePasswordFormAuthenticationListener( @@ -147,13 +150,17 @@ public function testHandleNonStringUsernameWithObject($postOnly) ['require_previous_session' => false, 'post_only' => $postOnly] ); $event = new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST); + + $this->expectException(BadRequestHttpException::class); + $this->expectExceptionMessage('The key "_username" must be a string, "object" given.'); + $listener($event); } /** * @dataProvider postOnlyDataProvider */ - public function testHandleNonStringUsernameWith__toString($postOnly) + public function testHandleNonStringUsernameWith__toString(bool $postOnly) { $usernameClass = $this->createMock(DummyUserClass::class); $usernameClass @@ -177,7 +184,63 @@ public function testHandleNonStringUsernameWith__toString($postOnly) $listener($event); } - public function postOnlyDataProvider() + /** + * @dataProvider provideInvalidCsrfTokens + */ + public function testInvalidCsrfToken($invalidToken) + { + $formBody = ['_username' => 'fabien', '_password' => 'symfony']; + if (null !== $invalidToken) { + $formBody['_csrf_token'] = $invalidToken; + } + + $request = Request::create('/login_check', 'POST', $formBody); + $request->setSession($this->createMock(SessionInterface::class)); + + $httpUtils = $this->createMock(HttpUtils::class); + $httpUtils + ->method('checkRequestPath') + ->willReturn(true) + ; + $httpUtils + ->method('createRedirectResponse') + ->willReturn(new RedirectResponse('/hello')) + ; + + $failureHandler = $this->createMock(AuthenticationFailureHandlerInterface::class); + $failureHandler + ->expects($this->once()) + ->method('onAuthenticationFailure') + ->willReturn(new Response()) + ; + + $authenticationManager = $this->createMock(AuthenticationProviderManager::class); + $authenticationManager + ->expects($this->never()) + ->method('authenticate') + ; + + $csrfTokenManager = $this->createMock(CsrfTokenManagerInterface::class); + $csrfTokenManager->method('isTokenValid')->willReturn(false); + + $listener = new UsernamePasswordFormAuthenticationListener( + $this->createMock(TokenStorageInterface::class), + $authenticationManager, + $this->createMock(SessionAuthenticationStrategyInterface::class), + $httpUtils, + 'TheProviderKey', + new DefaultAuthenticationSuccessHandler($httpUtils), + $failureHandler, + ['require_previous_session' => false], + null, + null, + $csrfTokenManager + ); + + $listener(new RequestEvent($this->createMock(HttpKernelInterface::class), $request, HttpKernelInterface::MASTER_REQUEST)); + } + + public function postOnlyDataProvider(): array { return [ [true], @@ -185,13 +248,22 @@ public function postOnlyDataProvider() ]; } - public function getUsernameForLength() + public function getUsernameForLength(): array { return [ [str_repeat('x', Security::MAX_USERNAME_LENGTH + 1), false], [str_repeat('x', Security::MAX_USERNAME_LENGTH - 1), true], ]; } + + public function provideInvalidCsrfTokens(): array + { + return [ + ['invalid'], + [['in' => 'valid']], + [null], + ]; + } } class DummyUserClass From 091769a34954a2b91e25df22ef1a4c93bd5d9676 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Wed, 18 Aug 2021 20:12:39 +0200 Subject: [PATCH 27/50] [PropertyInfo] Support for the never return type Signed-off-by: Alexander M. Turek <me@derrabus.de> --- .github/patch-types.php | 1 + .../PropertyInfo/Extractor/ReflectionExtractor.php | 2 +- .../Tests/Extractor/ReflectionExtractorTest.php | 10 +++++++++- .../PropertyInfo/Tests/Fixtures/Php81Dummy.php | 11 +++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php diff --git a/.github/patch-types.php b/.github/patch-types.php index 4d49778403fc3..a308eda397d51 100644 --- a/.github/patch-types.php +++ b/.github/patch-types.php @@ -42,6 +42,7 @@ case false !== strpos($file, '/src/Symfony/Component/ErrorHandler/Tests/Fixtures/'): case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php'): case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php'): + case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php'): case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/ReflectionIntersectionTypeFixture.php'): diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index d3b9b721e9c5f..0af4b9bf1bb36 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -335,7 +335,7 @@ private function extractFromReflectionType(\ReflectionType $reflectionType, \Ref foreach ($reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType] as $type) { $phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string) $type; - if ('null' === $phpTypeOrClass || 'mixed' === $phpTypeOrClass) { + if ('null' === $phpTypeOrClass || 'mixed' === $phpTypeOrClass || 'never' === $phpTypeOrClass) { continue; } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index 60b4efdbcf815..95e1ca5cda118 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -233,7 +233,7 @@ public function php71TypesProvider() } /** - * * @dataProvider php80TypesProvider + * @dataProvider php80TypesProvider * @requires PHP 8 */ public function testExtractPhp80Type($property, array $type = null) @@ -255,6 +255,14 @@ public function php80TypesProvider() ]; } + /** + * @requires PHP 8.1 + */ + public function testExtractPhp81Type() + { + $this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy', 'nothing', [])); + } + /** * @dataProvider defaultValueProvider */ diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php new file mode 100644 index 0000000000000..b4e896a434524 --- /dev/null +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php @@ -0,0 +1,11 @@ +<?php + +namespace Symfony\Component\PropertyInfo\Tests\Fixtures; + +class Php81Dummy +{ + public function getNothing(): never + { + throw new \Exception('Oops'); + } +} From ee614c3d30ec9f98fe92192627554a6ea65d647a Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Wed, 18 Aug 2021 21:10:23 +0200 Subject: [PATCH 28/50] Remove broken test case Signed-off-by: Alexander M. Turek <me@derrabus.de> --- .../DataTransformer/DateTimeToStringTransformerTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php index 60d9d5a84e428..dc01ba15503d9 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php @@ -17,9 +17,9 @@ class DateTimeToStringTransformerTest extends TestCase { - public function dataProvider() + public function dataProvider(): array { - $data = [ + return [ ['Y-m-d H:i:s', '2010-02-03 16:05:06', '2010-02-03 16:05:06 UTC'], ['Y-m-d H:i:00', '2010-02-03 16:05:00', '2010-02-03 16:05:00 UTC'], ['Y-m-d H:i', '2010-02-03 16:05', '2010-02-03 16:05:00 UTC'], @@ -36,7 +36,6 @@ public function dataProvider() // different day representations ['Y-m-j', '2010-02-3', '2010-02-03 00:00:00 UTC'], - ['z', '33', '1970-02-03 00:00:00 UTC'], // not bijective // this will not work as PHP will use actual date to replace missing info @@ -63,8 +62,6 @@ public function dataProvider() ['Y-z', '2010-33', '2010-02-03 00:00:00 UTC'], ]; - - return $data; } /** From 2155f76b6abf6352ec189d55e2199c4514af65fb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Thu, 19 Aug 2021 10:01:58 +0200 Subject: [PATCH 29/50] [Form] fix typo in Danish translation --- .../Component/Form/Resources/translations/validators.da.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.da.xlf b/src/Symfony/Component/Form/Resources/translations/validators.da.xlf index dafe20fa02c32..b4f078ff35f40 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.da.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.da.xlf @@ -120,7 +120,7 @@ </trans-unit> <trans-unit id="125"> <source>Please enter a valid email address.</source> - <target>Indtast venligst en gyldig emailaddresse.</target> + <target>Indtast venligst en gyldig e-mailadresse.</target> </trans-unit> <trans-unit id="126"> <source>Please select a valid option.</source> From e8f822df3f84a380c35b58ada8fb2bf957b930e2 Mon Sep 17 00:00:00 2001 From: Emre YILMAZ <33000794+EmreRed@users.noreply.github.com> Date: Thu, 19 Aug 2021 10:56:37 +0300 Subject: [PATCH 30/50] Update validators.tr.xlf --- .../Validator/Resources/translations/validators.tr.xlf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf index 6c39fac818238..8dc9c70de500d 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.tr.xlf @@ -386,6 +386,10 @@ <source>This value is not a valid International Securities Identification Number (ISIN).</source> <target>Bu değer geçerli bir Uluslararası Menkul Kıymetler Kimlik Numarası değil (ISIN).</target> </trans-unit> + <trans-unit id="100"> + <source>This value should be a valid expression.</source> + <target>Bu değer geçerli bir ifade olmalıdır.</target> + </trans-unit> </body> </file> </xliff> From d2f39e90536c960b48adfd709ed42484ab0978e9 Mon Sep 17 00:00:00 2001 From: Simon Ackermann <simon@hemmer.ch> Date: Mon, 16 Aug 2021 09:49:56 +0200 Subject: [PATCH 31/50] Remove polyfills from ExpressionLanguage --- src/Symfony/Component/ExpressionLanguage/Lexer.php | 6 +++--- src/Symfony/Component/ExpressionLanguage/composer.json | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Lexer.php b/src/Symfony/Component/ExpressionLanguage/Lexer.php index af859318d50d6..46d3e1c0c38e6 100644 --- a/src/Symfony/Component/ExpressionLanguage/Lexer.php +++ b/src/Symfony/Component/ExpressionLanguage/Lexer.php @@ -50,13 +50,13 @@ public function tokenize($expression) } $tokens[] = new Token(Token::NUMBER_TYPE, $number, $cursor + 1); $cursor += \strlen($match[0]); - } elseif (str_contains('([{', $expression[$cursor])) { + } elseif (false !== strpos('([{', $expression[$cursor])) { // opening bracket $brackets[] = [$expression[$cursor], $cursor]; $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); ++$cursor; - } elseif (str_contains(')]}', $expression[$cursor])) { + } elseif (false !== strpos(')]}', $expression[$cursor])) { // closing bracket if (empty($brackets)) { throw new SyntaxError(sprintf('Unexpected "%s".', $expression[$cursor]), $cursor, $expression); @@ -77,7 +77,7 @@ public function tokenize($expression) // operators $tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1); $cursor += \strlen($match[0]); - } elseif (str_contains('.,?:', $expression[$cursor])) { + } elseif (false !== strpos('.,?:', $expression[$cursor])) { // punctuation $tokens[] = new Token(Token::PUNCTUATION_TYPE, $expression[$cursor], $cursor + 1); ++$cursor; diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index 01922550ee40f..0e5cdadfb0573 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -18,7 +18,6 @@ "require": { "php": ">=7.1.3", "symfony/cache": "^3.4|^4.0|^5.0", - "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.1|^2" }, "autoload": { From d12382921ccd057c0ca470d22682309032b7a0cb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Wed, 25 Aug 2021 09:01:23 +0200 Subject: [PATCH 32/50] [HttpKernel] skip test on appveyor --- .../Component/HttpKernel/Tests/HttpKernelBrowserTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php index b32a8955f7372..78adfa72b71e1 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelBrowserTest.php @@ -143,6 +143,10 @@ public function testUploadedFileWhenNoFileSelected() public function testUploadedFileWhenSizeExceedsUploadMaxFileSize() { + if (UploadedFile::getMaxFilesize() > \PHP_INT_MAX) { + $this->markTestSkipped('Requires PHP_INT_MAX to be greater than "upload_max_filesize" and "post_max_size" ini settings'); + } + $source = tempnam(sys_get_temp_dir(), 'source'); $kernel = new TestHttpKernel(); From 4807fbc4429acfd860b42b224b338c50402fbab1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Wed, 25 Aug 2021 09:18:49 +0200 Subject: [PATCH 33/50] Fix tests --- src/Symfony/Component/Cache/Adapter/AbstractAdapter.php | 2 +- src/Symfony/Component/Cache/Adapter/ProxyAdapter.php | 2 +- src/Symfony/Component/Cache/Traits/ApcuTrait.php | 2 +- src/Symfony/Component/Cache/composer.json | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 040a095ab11ab..71338c3c12e0a 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -51,7 +51,7 @@ static function ($key, $value, $isHit) { // Detect wrapped values that encode for their expiry and creation duration // For compactness, these values are packed in the key of an array using // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) key($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { + if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { $item->value = $v[$k]; $v = unpack('Ve/Nc', substr($k, 1, -1)); $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index c9baa3ad3961f..d5b0593353ae9 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -59,7 +59,7 @@ static function ($key, $innerItem) use ($poolHash) { // Detect wrapped values that encode for their expiry and creation duration // For compactness, these values are packed in the key of an array using // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F - if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) key($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { + if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) { $item->value = $v[$k]; $v = unpack('Ve/Nc', substr($k, 1, -1)); $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET; diff --git a/src/Symfony/Component/Cache/Traits/ApcuTrait.php b/src/Symfony/Component/Cache/Traits/ApcuTrait.php index 9a02148c14dca..b56ae4f7c39ac 100644 --- a/src/Symfony/Component/Cache/Traits/ApcuTrait.php +++ b/src/Symfony/Component/Cache/Traits/ApcuTrait.php @@ -112,7 +112,7 @@ protected function doSave(array $values, int $lifetime) } catch (\Throwable $e) { if (1 === \count($values)) { // Workaround https://github.com/krakjoe/apcu/issues/170 - apcu_delete(key($values)); + apcu_delete(array_key_first($values)); } throw $e; diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index e481d66a9d427..d71f2169e03c2 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -25,6 +25,7 @@ "psr/cache": "^1.0|^2.0", "psr/log": "^1|^2|^3", "symfony/cache-contracts": "^1.1.7|^2", + "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.1|^2", "symfony/var-exporter": "^4.2|^5.0" From 9b6110bfaad5abfe4ec4f90506e8616cfbf48874 Mon Sep 17 00:00:00 2001 From: Martin Herndl <martin@herndl.org> Date: Wed, 4 Aug 2021 11:55:03 +0200 Subject: [PATCH 34/50] [FrameworkBundle] Fall back to default configuration in debug:config and consistently resolve parameter values --- .../Command/ConfigDebugCommand.php | 52 ++++++++++++++----- .../DefaultConfigTestBundle.php | 9 ++++ .../DependencyInjection/Configuration.php | 22 ++++++++ .../DefaultConfigTestExtension.php | 18 +++++++ .../ExtensionWithoutConfigTestExtension.php | 28 ++++++++++ .../ExtensionWithoutConfigTestBundle.php | 9 ++++ .../Functional/ConfigDebugCommandTest.php | 37 +++++++++++++ .../Functional/app/ConfigDump/bundles.php | 4 ++ .../Functional/app/ConfigDump/config.yml | 1 + 9 files changed, 166 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 7f0a7813a8ddd..a0623f396127b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Config\Definition\Processor; use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -18,6 +19,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\Compiler\ValidateEnvPlaceholdersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\Yaml\Yaml; /** @@ -77,22 +80,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $extension = $this->findExtension($name); - $container = $this->compileContainer(); - $extensionAlias = $extension->getAlias(); - $extensionConfig = []; - foreach ($container->getCompilerPassConfig()->getPasses() as $pass) { - if ($pass instanceof ValidateEnvPlaceholdersPass) { - $extensionConfig = $pass->getExtensionConfig(); - break; - } - } - - if (!isset($extensionConfig[$extensionAlias])) { - throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); - } + $container = $this->compileContainer(); - $config = $container->resolveEnvPlaceholders($extensionConfig[$extensionAlias]); + $config = $container->resolveEnvPlaceholders( + $container->getParameterBag()->resolveValue( + $this->getConfigForExtension($extension, $container) + ) + ); if (null === $path = $input->getArgument('path')) { $io->title( @@ -153,4 +148,33 @@ private function getConfigForPath(array $config, string $path, string $alias) return $config; } + + private function getConfigForExtension(ExtensionInterface $extension, ContainerBuilder $container): array + { + $extensionAlias = $extension->getAlias(); + + $extensionConfig = []; + foreach ($container->getCompilerPassConfig()->getPasses() as $pass) { + if ($pass instanceof ValidateEnvPlaceholdersPass) { + $extensionConfig = $pass->getExtensionConfig(); + break; + } + } + + if (isset($extensionConfig[$extensionAlias])) { + return $extensionConfig[$extensionAlias]; + } + + // Fall back to default config if the extension has one + + if (!$extension instanceof ConfigurationExtensionInterface) { + throw new \LogicException(sprintf('The extension with alias "%s" does not have configuration.', $extensionAlias)); + } + + $configs = $container->getExtensionConfig($extensionAlias); + $configuration = $extension->getConfiguration($configs, $container); + $this->validateConfiguration($extension, $configuration); + + return (new Processor())->processConfiguration($configuration, $configs); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php new file mode 100644 index 0000000000000..8c7a89574729f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DefaultConfigTestBundle.php @@ -0,0 +1,9 @@ +<?php + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class DefaultConfigTestBundle extends Bundle +{ +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php new file mode 100644 index 0000000000000..0c0812f3f9553 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/Configuration.php @@ -0,0 +1,22 @@ +<?php + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle\DependencyInjection; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; + +class Configuration implements ConfigurationInterface +{ + public function getConfigTreeBuilder(): TreeBuilder + { + $treeBuilder = new TreeBuilder('default_config_test'); + + $treeBuilder->getRootNode() + ->children() + ->scalarNode('foo')->defaultValue('%default_config_test_foo%')->end() + ->scalarNode('baz')->defaultValue('%env(BAZ)%')->end() + ->end(); + + return $treeBuilder; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php new file mode 100644 index 0000000000000..d380bcaad17fa --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/DefaultConfigTestBundle/DependencyInjection/DefaultConfigTestExtension.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; + +class DefaultConfigTestExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + + $container->setParameter('default_config_test', $config['foo']); + $container->setParameter('default_config_test', $config['baz']); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php new file mode 100644 index 0000000000000..e49f391bbafff --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php @@ -0,0 +1,28 @@ +<?php + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; + +class ExtensionWithoutConfigTestExtension implements ExtensionInterface +{ + public function load(array $configs, ContainerBuilder $container) + { + } + + public function getNamespace() + { + return ''; + } + + public function getXsdValidationBasePath() + { + return false; + } + + public function getAlias() + { + return 'extension_without_config_test'; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php new file mode 100644 index 0000000000000..5fe9fcdb7799f --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/ExtensionWithoutConfigTestBundle.php @@ -0,0 +1,9 @@ +<?php + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ExtensionWithoutConfigTestBundle extends Bundle +{ +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php index 3a0b095e32292..0df853997c59a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php @@ -58,6 +58,16 @@ public function testParametersValuesAreResolved() $this->assertStringContainsString('secret: test', $tester->getDisplay()); } + public function testDefaultParameterValueIsResolvedIfConfigIsExisting() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'framework']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $kernelCacheDir = $this->application->getKernel()->getContainer()->getParameter('kernel.cache_dir'); + $this->assertStringContainsString(sprintf("dsn: 'file:%s/profiler'", $kernelCacheDir), $tester->getDisplay()); + } + public function testDumpUndefinedBundleOption() { $tester = $this->createCommandTester(); @@ -74,6 +84,33 @@ public function testDumpWithPrefixedEnv() $this->assertStringContainsString("cookie_httponly: '%env(bool:COOKIE_HTTPONLY)%'", $tester->getDisplay()); } + public function testDumpFallsBackToDefaultConfigAndResolvesParameterValue() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'DefaultConfigTestBundle']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString('foo: bar', $tester->getDisplay()); + } + + public function testDumpFallsBackToDefaultConfigAndResolvesEnvPlaceholder() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(['name' => 'DefaultConfigTestBundle']); + + $this->assertSame(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString("baz: '%env(BAZ)%'", $tester->getDisplay()); + } + + public function testDumpThrowsExceptionWhenDefaultConfigFallbackIsImpossible() + { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The extension with alias "extension_without_config_test" does not have configuration.'); + + $tester = $this->createCommandTester(); + $tester->execute(['name' => 'ExtensionWithoutConfigTestBundle']); + } + private function createCommandTester(): CommandTester { $command = $this->application->find('debug:config'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php index 15ff182c6fed5..c4fb0bbe8ce48 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/bundles.php @@ -10,9 +10,13 @@ */ use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\DefaultConfigTestBundle\DefaultConfigTestBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ExtensionWithoutConfigTestBundle\ExtensionWithoutConfigTestBundle; use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; return [ + new DefaultConfigTestBundle(), + new ExtensionWithoutConfigTestBundle(), new FrameworkBundle(), new TestBundle(), ]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml index 432e35bd2f24d..a7a03a31d6602 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ConfigDump/config.yml @@ -11,3 +11,4 @@ parameters: env(LOCALE): en env(COOKIE_HTTPONLY): '1' secret: test + default_config_test_foo: bar From aec30217ce097ea32cdffecd4727190355cfd577 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Wed, 25 Aug 2021 21:27:26 +0200 Subject: [PATCH 35/50] Fix optional before mandatory parameters Signed-off-by: Alexander M. Turek <me@derrabus.de> --- src/Symfony/Component/Console/Event/ConsoleEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Event/ConsoleEvent.php b/src/Symfony/Component/Console/Event/ConsoleEvent.php index 5440da216c96f..400eb5731bad2 100644 --- a/src/Symfony/Component/Console/Event/ConsoleEvent.php +++ b/src/Symfony/Component/Console/Event/ConsoleEvent.php @@ -28,7 +28,7 @@ class ConsoleEvent extends Event private $input; private $output; - public function __construct(Command $command = null, InputInterface $input, OutputInterface $output) + public function __construct(?Command $command, InputInterface $input, OutputInterface $output) { $this->command = $command; $this->input = $input; From 7cc0c3670d10d2bb372caba3a9197b9b51d14953 Mon Sep 17 00:00:00 2001 From: "Roland Franssen :)" <franssen.roland@gmail.com> Date: Sun, 15 Aug 2021 13:06:47 +0200 Subject: [PATCH 36/50] [Translation] Reverse fallback locales --- .../Translation/Tests/TranslatorTest.php | 10 ++++++++-- .../Component/Translation/Translator.php | 18 ++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Translation/Tests/TranslatorTest.php b/src/Symfony/Component/Translation/Tests/TranslatorTest.php index b7d2d1cd18d58..073f2255fe7f4 100644 --- a/src/Symfony/Component/Translation/Tests/TranslatorTest.php +++ b/src/Symfony/Component/Translation/Tests/TranslatorTest.php @@ -304,11 +304,17 @@ public function testTransWithIcuVariantFallbackLocale() $translator->addResource('array', ['foo' => 'foofoo'], 'en_GB_scouse'); $translator->addResource('array', ['bar' => 'foobar'], 'en_GB'); $translator->addResource('array', ['baz' => 'foobaz'], 'en_001'); - $translator->addResource('array', ['qux' => 'fooqux'], 'en'); + $translator->addResource('array', ['bar' => 'en', 'qux' => 'fooqux'], 'en'); + $translator->addResource('array', ['bar' => 'nl_NL', 'fallback' => 'nl_NL'], 'nl_NL'); + $translator->addResource('array', ['bar' => 'nl', 'fallback' => 'nl'], 'nl'); + + $translator->setFallbackLocales(['nl_NL', 'nl']); + $this->assertSame('foofoo', $translator->trans('foo')); $this->assertSame('foobar', $translator->trans('bar')); $this->assertSame('foobaz', $translator->trans('baz')); $this->assertSame('fooqux', $translator->trans('qux')); + $this->assertSame('nl_NL', $translator->trans('fallback')); } public function testTransWithIcuRootFallbackLocale() @@ -358,7 +364,7 @@ public function testTransWithFallbackLocaleTer() $translator = new Translator('fr_FR'); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', ['foo' => 'foo (en_US)'], 'en_US'); - $translator->addResource('array', ['bar' => 'bar (en)'], 'en'); + $translator->addResource('array', ['foo' => 'foo (en)', 'bar' => 'bar (en)'], 'en'); $translator->setFallbackLocales(['en_US', 'en']); diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index c36ae331bac8c..5eb0183cbab43 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -462,14 +462,8 @@ protected function computeFallbackLocales($locale) $this->parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true); } + $originLocale = $locale; $locales = []; - foreach ($this->fallbackLocales as $fallback) { - if ($fallback === $locale) { - continue; - } - - $locales[] = $fallback; - } while ($locale) { $parent = $this->parentLocales[$locale] ?? null; @@ -490,10 +484,18 @@ protected function computeFallbackLocales($locale) } if (null !== $locale) { - array_unshift($locales, $locale); + $locales[] = $locale; } } + foreach ($this->fallbackLocales as $fallback) { + if ($fallback === $originLocale) { + continue; + } + + $locales[] = $fallback; + } + return array_unique($locales); } From 074539d3c9b889f8b33b30d09633f86de1247c03 Mon Sep 17 00:00:00 2001 From: Oleg Zhulnev <plbsid@gmail.com> Date: Fri, 11 Jun 2021 17:43:27 +0300 Subject: [PATCH 37/50] Fix Url Validator false positives --- src/Symfony/Component/Validator/Constraints/UrlValidator.php | 2 +- .../Validator/Tests/Constraints/UrlValidatorTest.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 68f26d08755fa..4d962eb098760 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -26,7 +26,7 @@ class UrlValidator extends ConstraintValidator (%s):// # protocol (((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+)@)? # basic auth ( - ([\pL\pN\pS\-\_\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name + ([\pL\pN\pS]+\.?[\pL\pN\pS\-\_]+)+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name | # or \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address | # or diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php index e154c6b2df9cc..ca2a27db4c780 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php @@ -105,6 +105,7 @@ public function getValidUrls() return [ ['http://a.pl'], ['http://www.example.com'], + ['http://tt.example.com'], ['http://www.example.com.'], ['http://www.example.museum'], ['https://example.com/'], @@ -265,6 +266,10 @@ public function getInvalidUrls() ['http://example.com/exploit.html?hel lo'], ['http://example.com/exploit.html?not_a%hex'], ['http://'], + ['http://www..com'], + ['http://www..example.com'], + ['http://wwww.example..com'], + ['http://.www.example.com'], ]; } From 77bd21adfcb89b8c41154f4367089beb365ae150 Mon Sep 17 00:00:00 2001 From: Volker Killesreiter <killesre@gmail.com> Date: Tue, 30 Mar 2021 17:03:07 +0200 Subject: [PATCH 38/50] [HttpFoundation] Fix isNotModified determination logic --- .../Component/HttpFoundation/Request.php | 2 +- .../Component/HttpFoundation/Response.php | 25 +++++++++--- .../HttpFoundation/Tests/ResponseTest.php | 40 +++++++++++++++++-- .../HttpKernel/HttpCache/HttpCache.php | 17 ++++++-- .../Tests/HttpCache/HttpCacheTest.php | 4 +- .../Component/HttpKernel/composer.json | 2 +- 6 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index cf6ebbc0b0903..98e2efef45292 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1564,7 +1564,7 @@ public function getContent($asResource = false) */ public function getETags() { - return preg_split('/\s*,\s*/', $this->headers->get('if_none_match', ''), -1, \PREG_SPLIT_NO_EMPTY); + return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY); } /** diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 4ab97aaf90538..3c0950f3384cf 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -1079,12 +1079,27 @@ public function isNotModified(Request $request): bool $lastModified = $this->headers->get('Last-Modified'); $modifiedSince = $request->headers->get('If-Modified-Since'); - if ($etags = $request->getETags()) { - $notModified = \in_array($this->getEtag(), $etags) || \in_array('*', $etags); - } + if ($ifNoneMatchEtags = $request->getETags()) { + $etag = $this->getEtag(); + if (0 == strncmp($etag, 'W/', 2)) { + $etag = substr($etag, 2); + } + + // Use weak comparison as per https://tools.ietf.org/html/rfc7232#section-3.2. + foreach ($ifNoneMatchEtags as $ifNoneMatchEtag) { + if (0 == strncmp($ifNoneMatchEtag, 'W/', 2)) { + $ifNoneMatchEtag = substr($ifNoneMatchEtag, 2); + } - if ($modifiedSince && $lastModified) { - $notModified = strtotime($modifiedSince) >= strtotime($lastModified) && (!$etags || $notModified); + if ($ifNoneMatchEtag === $etag || '*' === $ifNoneMatchEtag) { + $notModified = true; + break; + } + } + } + // Only do If-Modified-Since date comparison when If-None-Match is not present as per https://tools.ietf.org/html/rfc7232#section-3.3. + elseif ($modifiedSince && $lastModified) { + $notModified = strtotime($modifiedSince) >= strtotime($lastModified); } if ($notModified) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php index f26302eef1120..b6d714ae5973d 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php @@ -194,7 +194,7 @@ public function testIsNotModifiedEtag() $etagTwo = 'randomly_generated_etag_2'; $request = new Request(); - $request->headers->set('if_none_match', sprintf('%s, %s, %s', $etagOne, $etagTwo, 'etagThree')); + $request->headers->set('If-None-Match', sprintf('%s, %s, %s', $etagOne, $etagTwo, 'etagThree')); $response = new Response(); @@ -206,6 +206,38 @@ public function testIsNotModifiedEtag() $response->headers->set('ETag', ''); $this->assertFalse($response->isNotModified($request)); + + // Test wildcard + $request = new Request(); + $request->headers->set('If-None-Match', '*'); + + $response->headers->set('ETag', $etagOne); + $this->assertTrue($response->isNotModified($request)); + } + + public function testIsNotModifiedWeakEtag() + { + $etag = 'randomly_generated_etag'; + $weakEtag = 'W/randomly_generated_etag'; + + $request = new Request(); + $request->headers->set('If-None-Match', $etag); + $response = new Response(); + + $response->headers->set('ETag', $etag); + $this->assertTrue($response->isNotModified($request)); + + $response->headers->set('ETag', $weakEtag); + $this->assertTrue($response->isNotModified($request)); + + $request->headers->set('If-None-Match', $weakEtag); + $response = new Response(); + + $response->headers->set('ETag', $etag); + $this->assertTrue($response->isNotModified($request)); + + $response->headers->set('ETag', $weakEtag); + $this->assertTrue($response->isNotModified($request)); } public function testIsNotModifiedLastModifiedAndEtag() @@ -216,14 +248,14 @@ public function testIsNotModifiedLastModifiedAndEtag() $etag = 'randomly_generated_etag'; $request = new Request(); - $request->headers->set('if_none_match', sprintf('%s, %s', $etag, 'etagThree')); + $request->headers->set('If-None-Match', sprintf('%s, %s', $etag, 'etagThree')); $request->headers->set('If-Modified-Since', $modified); $response = new Response(); $response->headers->set('ETag', $etag); $response->headers->set('Last-Modified', $after); - $this->assertFalse($response->isNotModified($request)); + $this->assertTrue($response->isNotModified($request)); $response->headers->set('ETag', 'non-existent-etag'); $response->headers->set('Last-Modified', $before); @@ -240,7 +272,7 @@ public function testIsNotModifiedIfModifiedSinceAndEtagWithoutLastModified() $etag = 'randomly_generated_etag'; $request = new Request(); - $request->headers->set('if_none_match', sprintf('%s, %s', $etag, 'etagThree')); + $request->headers->set('If-None-Match', sprintf('%s, %s', $etag, 'etagThree')); $request->headers->set('If-Modified-Since', $modified); $response = new Response(); diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 6c4715802efda..be7042279483a 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -1,5 +1,14 @@ <?php +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + /* * This file is part of the Symfony package. * @@ -382,7 +391,7 @@ protected function validate(Request $request, Response $entry, $catch = false) // add our cached last-modified validator if ($entry->headers->has('Last-Modified')) { - $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified')); + $subRequest->headers->set('If-Modified-Since', $entry->headers->get('Last-Modified')); } // Add our cached etag validator to the environment. @@ -391,7 +400,7 @@ protected function validate(Request $request, Response $entry, $catch = false) $cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : []; $requestEtags = $request->getETags(); if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { - $subRequest->headers->set('if_none_match', implode(', ', $etags)); + $subRequest->headers->set('If-None-Match', implode(', ', $etags)); } $response = $this->forward($subRequest, $catch, $entry); @@ -444,8 +453,8 @@ protected function fetch(Request $request, $catch = false) } // avoid that the backend sends no content - $subRequest->headers->remove('if_modified_since'); - $subRequest->headers->remove('if_none_match'); + $subRequest->headers->remove('If-Modified-Since'); + $subRequest->headers->remove('If-None-Match'); $response = $this->forward($subRequest, $catch); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index 9bec2f7c94eb1..fc363862ea680 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -156,7 +156,7 @@ public function testRespondsWith304WhenIfNoneMatchMatchesETag() $this->assertTraceContains('store'); } - public function testRespondsWith304OnlyIfIfNoneMatchAndIfModifiedSinceBothMatch() + public function testRespondsWith304WhenIfNoneMatchAndIfModifiedSinceBothMatch() { $time = \DateTime::createFromFormat('U', time()); @@ -172,7 +172,7 @@ public function testRespondsWith304OnlyIfIfNoneMatchAndIfModifiedSinceBothMatch( $t = \DateTime::createFromFormat('U', time() - 3600); $this->request('GET', '/', ['HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $t->format(\DATE_RFC2822)]); $this->assertHttpKernelIsCalled(); - $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals(304, $this->response->getStatusCode()); // only Last-Modified matches $this->request('GET', '/', ['HTTP_IF_NONE_MATCH' => '1234', 'HTTP_IF_MODIFIED_SINCE' => $time->format(\DATE_RFC2822)]); diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index a2fa2a0ecac5d..74ce9aadb05db 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -20,7 +20,7 @@ "symfony/error-handler": "^4.4", "symfony/event-dispatcher": "^4.4", "symfony/http-client-contracts": "^1.1|^2", - "symfony/http-foundation": "^4.4|^5.0", + "symfony/http-foundation": "^4.4.24|^5.2.9", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.15", From 34d43aa2eb8f034c2f1c7525f5b3fc8561a7c5c1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier <fabien@potencier.org> Date: Thu, 26 Aug 2021 08:31:37 +0200 Subject: [PATCH 39/50] Remove redundant license info --- src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index be7042279483a..7deda42fc7186 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -10,16 +10,9 @@ */ /* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; From 7995559e8291d9519b802a22668c33177c2dc367 Mon Sep 17 00:00:00 2001 From: Fabien Potencier <fabien@potencier.org> Date: Thu, 26 Aug 2021 08:31:47 +0200 Subject: [PATCH 40/50] Fix composer.json versions --- src/Symfony/Component/HttpKernel/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 9a44848d460ac..c2758e45ae8cc 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -20,7 +20,7 @@ "symfony/error-handler": "^4.4", "symfony/event-dispatcher": "^4.4", "symfony/http-client-contracts": "^1.1|^2", - "symfony/http-foundation": "^4.4.24|^5.2.9", + "symfony/http-foundation": "^4.4.30|^5.3.7", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", From 8be1f8b22988a9d7b5c1b8ca6cfd56b633b0ffb2 Mon Sep 17 00:00:00 2001 From: Fabien Potencier <fabien@potencier.org> Date: Thu, 26 Aug 2021 08:53:21 +0200 Subject: [PATCH 41/50] Fix composer.json versions --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 7fe4a67faac44..6562fa2d1e241 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -39,7 +39,7 @@ "symfony/browser-kit": "^4.3|^5.0", "symfony/console": "^4.4.21|^5.0", "symfony/css-selector": "^3.4|^4.0|^5.0", - "symfony/dom-crawler": "^4.4.20|^5.2.4", + "symfony/dom-crawler": "^4.4.30|^5.3.7", "symfony/dotenv": "^4.3.6|^5.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/form": "^4.3.5|^5.0", From f4df2055bfc052fedf099f91ba9a920bb8e6357d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Thu, 26 Aug 2021 10:36:58 +0200 Subject: [PATCH 42/50] fix cs --- .../ExtensionWithoutConfigTestExtension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php index e49f391bbafff..79f0a7006c89b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ExtensionWithoutConfigTestBundle/DependencyInjection/ExtensionWithoutConfigTestExtension.php @@ -11,7 +11,7 @@ public function load(array $configs, ContainerBuilder $container) { } - public function getNamespace() + public function getNamespace(): string { return ''; } @@ -21,7 +21,7 @@ public function getXsdValidationBasePath() return false; } - public function getAlias() + public function getAlias(): string { return 'extension_without_config_test'; } From 8c3c0a39ec27c8e9b7579c2e58109e367bfffe37 Mon Sep 17 00:00:00 2001 From: Jeroen Noten <jeroen.noten@isaac.nl> Date: Mon, 2 Aug 2021 14:02:06 +0200 Subject: [PATCH 43/50] Remove indices in messenger table on MySQL to prevent deadlocks while removing messages when running multiple consumers SELECT ... FOR UPDATE row locks also locks indices. Since locking rows and indices is not one atomic operation, this might cause deadlocks when running multiple workers. Removing indices on queue_name and available_at resolves this problem. --- .../Transport/Doctrine/ConnectionTest.php | 54 +++++++++++++++++++ .../Transport/Doctrine/Connection.php | 9 ++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php index c7575e9b8746a..d8b1447257ba1 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Doctrine/ConnectionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Messenger\Tests\Transport\Doctrine; use Doctrine\DBAL\Abstraction\Result as AbstractionResult; +use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection as DBALConnection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\Result as DriverResult; @@ -23,8 +24,11 @@ use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\AbstractSchemaManager; +use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\SchemaConfig; +use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Statement; +use Doctrine\DBAL\Types\Types; use PHPUnit\Framework\TestCase; use Symfony\Component\Messenger\Exception\InvalidArgumentException; use Symfony\Component\Messenger\Exception\TransportException; @@ -402,4 +406,54 @@ public function providePlatformSql(): iterable 'SELECT m.* FROM messenger_messages m WITH (UPDLOCK, ROWLOCK) WHERE (m.delivered_at is null OR m.delivered_at < ?) AND (m.available_at <= ?) AND (m.queue_name = ?) ORDER BY available_at ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY ', ]; } + + /** + * @dataProvider setupIndicesProvider + */ + public function testSetupIndices(string $platformClass, array $expectedIndices) + { + $driverConnection = $this->createMock(DBALConnection::class); + $driverConnection->method('getConfiguration')->willReturn(new Configuration()); + + $schemaManager = $this->createMock(AbstractSchemaManager::class); + $schema = new Schema(); + $expectedTable = $schema->createTable('messenger_messages'); + $expectedTable->addColumn('id', Types::BIGINT); + $expectedTable->setPrimaryKey(['id']); + // Make sure columns for indices exists so addIndex() will not throw + foreach (array_unique(array_merge(...$expectedIndices)) as $columnName) { + $expectedTable->addColumn($columnName, Types::STRING); + } + foreach ($expectedIndices as $indexColumns) { + $expectedTable->addIndex($indexColumns); + } + $schemaManager->method('createSchema')->willReturn($schema); + $driverConnection->method('getSchemaManager')->willReturn($schemaManager); + + $platformMock = $this->createMock($platformClass); + $platformMock + ->expects(self::once()) + ->method('getAlterTableSQL') + ->with(self::callback(static function (TableDiff $tableDiff): bool { + return 0 === \count($tableDiff->addedIndexes) && 0 === \count($tableDiff->changedIndexes) && 0 === \count($tableDiff->removedIndexes); + })) + ->willReturn([]); + $driverConnection->method('getDatabasePlatform')->willReturn($platformMock); + + $connection = new Connection([], $driverConnection); + $connection->setup(); + } + + public function setupIndicesProvider(): iterable + { + yield 'MySQL' => [ + MySQL57Platform::class, + [['delivered_at']], + ]; + + yield 'Other platforms' => [ + AbstractPlatform::class, + [['queue_name'], ['available_at'], ['delivered_at']], + ]; + } } diff --git a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php index 20098e2283669..e936ca09e871f 100644 --- a/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php +++ b/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php @@ -17,6 +17,7 @@ use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception\TableNotFoundException; use Doctrine\DBAL\LockMode; +use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\Comparator; @@ -386,7 +387,6 @@ private function getSchema(): Schema $table->addColumn('headers', self::$useDeprecatedConstants ? Type::TEXT : Types::TEXT) ->setNotnull(true); $table->addColumn('queue_name', self::$useDeprecatedConstants ? Type::STRING : Types::STRING) - ->setLength(190) // MySQL 5.6 only supports 191 characters on an indexed column in utf8mb4 mode ->setNotnull(true); $table->addColumn('created_at', self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE) ->setNotnull(true); @@ -395,8 +395,11 @@ private function getSchema(): Schema $table->addColumn('delivered_at', self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE) ->setNotnull(false); $table->setPrimaryKey(['id']); - $table->addIndex(['queue_name']); - $table->addIndex(['available_at']); + // No indices on queue_name and available_at on MySQL to prevent deadlock issues when running multiple consumers. + if (!$this->driverConnection->getDatabasePlatform() instanceof MySqlPlatform) { + $table->addIndex(['queue_name']); + $table->addIndex(['available_at']); + } $table->addIndex(['delivered_at']); return $schema; From d1eda26a92f2fca20cedd3415b5c6efef3e38d8b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas <nicolas.grekas@gmail.com> Date: Thu, 26 Aug 2021 15:38:20 +0200 Subject: [PATCH 44/50] Add no-interaction for SYMFONY_PHPUNIT_REMOVE --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index c43a1ccff1e04..179280b87b510 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -226,7 +226,7 @@ @copy("$PHPUNIT_VERSION_DIR/phpunit.xsd", 'phpunit.xsd'); chdir("$PHPUNIT_VERSION_DIR"); if ($SYMFONY_PHPUNIT_REMOVE) { - $passthruOrFail("$COMPOSER remove --no-update ".$SYMFONY_PHPUNIT_REMOVE); + $passthruOrFail("$COMPOSER remove --no-update --no-interaction ".$SYMFONY_PHPUNIT_REMOVE); } if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) { $passthruOrFail("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\""); From c56470dbc7706da583d6503cb458a60b0a85315e Mon Sep 17 00:00:00 2001 From: Nate Wiebe <nate@northern.co> Date: Thu, 26 Aug 2021 10:33:21 -0400 Subject: [PATCH 45/50] Cast ini_get to an integer to match expected type --- .../HttpFoundation/Session/Storage/MetadataBag.php | 2 +- .../Tests/Session/Storage/MetadataBagTest.php | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php index 0146ee259b384..8efdb856f16e5 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php @@ -163,6 +163,6 @@ private function stampCreated(int $lifetime = null): void { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = $lifetime ?? ini_get('session.cookie_lifetime'); + $this->meta[self::LIFETIME] = $lifetime ?? (int) ini_get('session.cookie_lifetime'); } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php index e040f4862755b..51a1b6472f764 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MetadataBagTest.php @@ -136,4 +136,14 @@ public function testDoesNotSkipLastUsedUpdate() $this->assertEquals($timeStamp, $sessionMetadata[MetadataBag::UPDATED]); } + + public function testLifetimeIsInt() + { + $sessionMetadata = []; + + $bag = new MetadataBag(); + $bag->initialize($sessionMetadata); + + $this->assertIsInt($bag->getLifetime()); + } } From a0e8f4fdb33441356f42b2639ac4ff143c0f6148 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Fri, 27 Aug 2021 19:42:48 +0200 Subject: [PATCH 46/50] Fix test fatal_with_nested_handlers for PHP 8.1 Signed-off-by: Alexander M. Turek <me@derrabus.de> --- .../phpt/fatal_with_nested_handlers.phpt | 8 ++- .../fatal_with_nested_handlers_pre81.phpt | 55 +++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers_pre81.phpt diff --git a/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt b/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt index 15933828bd426..92f7e12fde227 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt +++ b/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers.phpt @@ -1,5 +1,7 @@ --TEST-- Test catching fatal errors when handlers are nested +--SKIPIF-- +<?php if (\PHP_VERSION_ID < 80100) echo 'skip' ?> --FILE-- <?php @@ -36,6 +38,9 @@ array(1) { string(37) "Error and exception handlers do match" } object(Symfony\Component\ErrorHandler\Error\FatalError)#%d (%d) { + ["message":protected]=> + string(186) "Error: Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)" +%a ["error":"Symfony\Component\ErrorHandler\Error\FatalError":private]=> array(4) { ["type"]=> @@ -47,7 +52,4 @@ object(Symfony\Component\ErrorHandler\Error\FatalError)#%d (%d) { ["line"]=> int(%d) } - ["message":protected]=> - string(186) "Error: Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)" -%a } diff --git a/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers_pre81.phpt b/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers_pre81.phpt new file mode 100644 index 0000000000000..d6b2baa6c904d --- /dev/null +++ b/src/Symfony/Component/ErrorHandler/Tests/phpt/fatal_with_nested_handlers_pre81.phpt @@ -0,0 +1,55 @@ +--TEST-- +Test catching fatal errors when handlers are nested +--SKIPIF-- +<?php if (\PHP_VERSION_ID >= 80100) echo 'skip' ?> +--FILE-- +<?php + +namespace Symfony\Component\ErrorHandler; + +$vendor = __DIR__; +while (!file_exists($vendor.'/vendor')) { + $vendor = \dirname($vendor); +} +require $vendor.'/vendor/autoload.php'; + +Debug::enable(); +ini_set('display_errors', 0); + +$eHandler = set_error_handler('var_dump'); +$xHandler = set_exception_handler('var_dump'); + +var_dump([ + $eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different', +]); + +$eHandler[0]->setExceptionHandler('print_r'); + +if (true) { + class Broken implements \JsonSerializable + { + } +} + +?> +--EXPECTF-- +array(1) { + [0]=> + string(37) "Error and exception handlers do match" +} +object(Symfony\Component\ErrorHandler\Error\FatalError)#%d (%d) { + ["error":"Symfony\Component\ErrorHandler\Error\FatalError":private]=> + array(4) { + ["type"]=> + int(1) + ["message"]=> + string(179) "Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(%d) + } + ["message":protected]=> + string(186) "Error: Class Symfony\Component\ErrorHandler\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)" +%a +} From 51eda098edffdaa9fba1fea6f29ca27d23c3d752 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" <me@derrabus.de> Date: Sat, 28 Aug 2021 17:30:46 +0200 Subject: [PATCH 47/50] [DomCrawler] Don't pass null to trim() Signed-off-by: Alexander M. Turek <me@derrabus.de> --- .../Test/Constraint/CrawlerSelectorAttributeValueSame.php | 2 +- .../Test/Constraint/CrawlerSelectorAttributeValueSameTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorAttributeValueSame.php b/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorAttributeValueSame.php index 7008779e14203..a198784d448df 100644 --- a/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorAttributeValueSame.php +++ b/src/Symfony/Component/DomCrawler/Test/Constraint/CrawlerSelectorAttributeValueSame.php @@ -47,7 +47,7 @@ protected function matches($crawler): bool return false; } - return $this->expectedText === trim($crawler->attr($this->attribute)); + return $this->expectedText === trim($crawler->attr($this->attribute) ?? ''); } /** diff --git a/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorAttributeValueSameTest.php b/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorAttributeValueSameTest.php index ab528ab356443..47ecdc8a04438 100644 --- a/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorAttributeValueSameTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/Test/Constraint/CrawlerSelectorAttributeValueSameTest.php @@ -23,6 +23,7 @@ public function testConstraint() { $constraint = new CrawlerSelectorAttributeValueSame('input[name="username"]', 'value', 'Fabien'); $this->assertTrue($constraint->evaluate(new Crawler('<html><body><form><input type="text" name="username" value="Fabien">'), '', true)); + $this->assertFalse($constraint->evaluate(new Crawler('<html><body><form><input type="text" name="username">'), '', true)); $this->assertFalse($constraint->evaluate(new Crawler('<html><head><title>Bar'), '', true)); try { From 1a13f06989808373627fdace709a69e1eac87cbc Mon Sep 17 00:00:00 2001 From: Fabien Potencier <fabien@potencier.org> Date: Mon, 30 Aug 2021 14:27:11 +0200 Subject: [PATCH 48/50] Update CHANGELOG for 4.4.30 --- CHANGELOG-4.4.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG-4.4.md b/CHANGELOG-4.4.md index 40d08340ad617..2067112f91c93 100644 --- a/CHANGELOG-4.4.md +++ b/CHANGELOG-4.4.md @@ -7,6 +7,24 @@ in 4.4 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.4.0...v4.4.1 +* 4.4.30 (2021-08-30) + + * bug #42753 Cast ini_get to an integer to match expected type (natewiebe13) + * bug #42345 [Messenger] Remove indices in messenger table on MySQL to prevent deadlocks while removing messages when running multiple consumers (jeroennoten) + * bug #40744 allow null for framework.translator.default_path (SimonHeimberg) + * bug #39856 [DomCrawler] improve failure messages of the CrawlerSelectorTextContains constraint (xabbuh) + * bug #40545 [HttpFoundation] Fix isNotModified determination logic (ol0lll) + * bug #42368 [FrameworkBundle] Fall back to default configuration in debug:config and consistently resolve parameter values (herndlm) + * bug #41684 Fix Url Validator false positives (sidz) + * bug #42576 [Translation] Reverse fallback locales (ro0NL) + * bug #42628 [PropertyInfo] Support for the `never` return type (derrabus) + * bug #42585 [ExpressionLanguage] [Lexer] Remove PHP 8.0 polyfill (nigelmann) + * bug #42621 [Security] Don't produce TypeErrors for non-string CSRF tokens (derrabus) + * bug #42365 [Cache] Do not add namespace argument to `NullAdapter` in `CachePoolPass` (olsavmic) + * bug #42331 [HttpKernel] always close open stopwatch section after handling `kernel.request` events (xabbuh) + * bug #42260 Fix return types for PHP 8.1 (derrabus) + * bug #42341 [Validator] Update MIR card scheme (ossinkine) + * 4.4.29 (2021-07-29) * bug #42307 [Mailer] Fixed decode exception when sendgrid response is 202 (rubanooo) From 0c6f25fc3ae70762c3efe3921a56d883790958ec Mon Sep 17 00:00:00 2001 From: Fabien Potencier <fabien@potencier.org> Date: Mon, 30 Aug 2021 14:27:17 +0200 Subject: [PATCH 49/50] Update CONTRIBUTORS for 4.4.30 --- CONTRIBUTORS.md | 93 +++++++++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5c9b27862671f..f804602f54457 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -12,10 +12,10 @@ The Symfony Connect username in parenthesis allows to get more information - Tobias Schultze (tobion) - Robin Chalas (chalas_r) - Christophe Coevoet (stof) + - Wouter De Jong (wouterj) - Jérémy DERUSSÉ (jderusse) - Maxime Steinhausser (ogizanagi) - Kévin Dunglas (dunglas) - - Wouter De Jong (wouterj) - Grégoire Pineau (lyrixx) - Jordi Boggiano (seldaek) - Victor Berchet (victor) @@ -48,11 +48,11 @@ The Symfony Connect username in parenthesis allows to get more information - Eriksen Costa (eriksencosta) - Ener-Getick (energetick) - Sarah Khalil (saro0h) - - Pierre du Plessis (pierredup) - Kevin Bond (kbond) + - Pierre du Plessis (pierredup) + - Valentin Udaltsov (vudaltsov) - Iltar van der Berg (kjarli) - Jonathan Wage (jwage) - - Valentin Udaltsov (vudaltsov) - Matthias Pigulla (mpdude) - Vasilij Duško (staff) - Diego Saint Esteben (dosten) @@ -91,6 +91,7 @@ The Symfony Connect username in parenthesis allows to get more information - Issei Murasawa (issei_m) - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) + - Antoine M (amakdessi) - Vasilij Dusko - Douglas Greenshields (shieldo) - Graham Campbell (graham) @@ -99,7 +100,6 @@ The Symfony Connect username in parenthesis allows to get more information - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Antoine M (amakdessi) - Fran Moreno (franmomu) - Dariusz Ruminski - Jérôme Vasseur (jvasseur) @@ -112,26 +112,27 @@ The Symfony Connect username in parenthesis allows to get more information - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - John Wards (johnwards) + - Alexander Schranz (alexander-schranz) - Baptiste Clavié (talus) - Antoine Hérault (herzult) - Paráda József (paradajozsef) - - Alexander Schranz (alexander-schranz) - Arnaud Le Blanc (arnaud-lb) - Przemysław Bogusz (przemyslaw-bogusz) + - Vincent Langlet (deviling) - Maxime STEINHAUSSER + - Tomas Norkūnas (norkunas) - Michal Piotrowski (eventhorizon) - Tomáš Votruba (tomas_votruba) - Massimiliano Arione (garak) - Mathias Arlaud (mtarld) - Tim Nagel (merk) - - Vincent Langlet (deviling) - Chris Wilkinson (thewilkybarkid) - - Tomas Norkūnas (norkunas) - Peter Kokot (maastermedia) - Lars Strojny (lstrojny) - Brice BERNARD (brikou) - Ahmed TAILOULOUTE (ahmedtai) - Gregor Harlan (gharlan) + - HypeMC (hypemc) - marc.weistroff - lenar - Alexander Schwenn (xelaris) @@ -144,29 +145,29 @@ The Symfony Connect username in parenthesis allows to get more information - Jacob Dreesen (jdreesen) - Malte Schlüter (maltemaltesich) - Joel Wurtz (brouznouf) + - Théo FIDRY (theofidry) - Florian Voutzinos (florianv) - Teoh Han Hui (teohhanhui) - Colin Frei - Javier Spagnoletti (phansys) - Joshua Thijssen - - HypeMC (hypemc) - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - excelwebzone - Gordon Franke (gimler) - Saif Eddin Gmati (azjezz) + - Alexandre Daubois (alexandre-daubois) - Jesse Rushlow (geeshoe) - Fabien Pennequin (fabienpennequin) - - Théo FIDRY (theofidry) - Olivier Dolbeau (odolbeau) - - Alexandre Daubois (alexandre-daubois) + - Smaine Milianni (ismail1432) + - Richard van Laak (rvanlaak) - Eric GELOEN (gelo) - Matthieu Napoli (mnapoli) - Jannik Zschiesche (apfelbox) - Mathieu Santostefano (welcomattic) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) - - Richard van Laak (rvanlaak) - Tigran Azatyan (tigranazatyan) - YaFou - Gary PEGEOT (gary-p) @@ -183,10 +184,10 @@ The Symfony Connect username in parenthesis allows to get more information - Hidenori Goto (hidenorigoto) - Jan Rosier (rosier) - Alessandro Chitolina (alekitto) + - Ruud Kamphuis (ruudk) - Albert Casademont (acasademont) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) - - Smaine Milianni (ismail1432) - SpacePossum - Pablo Godel (pgodel) - Andreas Braun @@ -194,7 +195,6 @@ The Symfony Connect username in parenthesis allows to get more information - François-Xavier de Guillebon (de-gui_f) - Oleg Voronkovich - hacfi (hifi) - - Ruud Kamphuis (ruudk) - Rafael Dohms (rdohms) - George Mponos (gmponos) - jwdeitch @@ -215,6 +215,7 @@ The Symfony Connect username in parenthesis allows to get more information - Timo Bakx (timobakx) - Marco Pivetta (ocramius) - Vincent Touzet (vincenttouzet) + - Nate Wiebe (natewiebe13) - Rouven Weßling (realityking) - Jérôme Parmentier (lctrs) - Ben Davies (bendavies) @@ -248,6 +249,7 @@ The Symfony Connect username in parenthesis allows to get more information - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - Mathieu Lechat (mat_the_cat) + - Jeroen Noten (jeroennoten) - Marek Štípek (maryo) - Daniel Espendiller - Possum @@ -263,7 +265,6 @@ The Symfony Connect username in parenthesis allows to get more information - Hidde Wieringa (hiddewie) - Antonio Pauletich (x-coder264) - Andre Rømcke (andrerom) - - Nate Wiebe (natewiebe13) - Philippe Segatori - Thibaut Cheymol (tcheymol) - Sebastien Morel (plopix) @@ -287,10 +288,10 @@ The Symfony Connect username in parenthesis allows to get more information - François Pluchino (francoispluchino) - Rokas Mikalkėnas (rokasm) - bronze1man - - Jeroen Noten (jeroennoten) - sun (sun) - Larry Garfield (crell) - Edi Modrić (emodric) + - Gocha Ossinkine (ossinkine) - Roman Martinuk (a2a4) - Leo Feyer (leofeyer) - Nikolay Labinskiy (e-moe) @@ -314,8 +315,10 @@ The Symfony Connect username in parenthesis allows to get more information - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) + - zairig imad (zairigimad) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) + - Maciej Malarz (malarzm) - Michele Orselli (orso) - Sven Paulus (subsven) - Daniel STANCU @@ -330,7 +333,6 @@ The Symfony Connect username in parenthesis allows to get more information - Bohan Yang (brentybh) - Pascal Montoya - Julien Brochet (mewt) - - Gocha Ossinkine (ossinkine) - Tristan Darricau (nicofuma) - Victor Bocharsky (bocharsky_bw) - Bozhidar Hristov (warxcell) @@ -360,12 +362,10 @@ The Symfony Connect username in parenthesis allows to get more information - Manuel Reinhard (sprain) - Harm van Tilborg (hvt) - Danny Berger (dpb587) - - zairig imad (zairigimad) - Antonio J. García Lagar (ajgarlag) - Adam Prager (padam87) - Judicaël RUFFIEUX (axanagor) - Benoît Burnichon (bburnichon) - - Maciej Malarz (malarzm) - Roman Marintšenko (inori) - Xavier Montaña Carreras (xmontana) - Mickaël Andrieu (mickaelandrieu) @@ -400,6 +400,7 @@ The Symfony Connect username in parenthesis allows to get more information - Bob den Otter (bopp) - Thomas Schulz (king2500) - Frank de Jonge (frenkynet) + - Artem Henvald (artemgenvald) - Lescot Edouard (idetox) - Nikita Konstantinov - Wodor Wodorski @@ -422,10 +423,12 @@ The Symfony Connect username in parenthesis allows to get more information - Roumen Damianoff (roumen) - Kim Hemsø Rasmussen (kimhemsoe) - Oleg Andreyev + - Martin Herndl (herndlm) - Pavel Kirpitsov (pavel-kirpichyov) - Pascal Luna (skalpa) - Wouter Van Hecke - Iker Ibarguren (ikerib) + - Bob van de Vijver (bobvandevijver) - Peter Kruithof (pkruithof) - Michael Holm (hollo) - Sylvain Fabre (sylfabre) @@ -437,6 +440,7 @@ The Symfony Connect username in parenthesis allows to get more information - Gonzalo Vilaseca (gonzalovilaseca) - Ben Hakim - Haralan Dobrev (hkdobrev) + - Marco Petersen (ocrampete16) - MatTheCat - Vilius Grigaliūnas - David Badura (davidbadura) @@ -493,7 +497,6 @@ The Symfony Connect username in parenthesis allows to get more information - Oleksandr Barabolia (oleksandrbarabolia) - Christopher Davis (chrisguitarguy) - ivan - - Artem Henvald (artemgenvald) - Greg Anderson - Tri Pham (phamuyentri) - BoShurik @@ -519,15 +522,14 @@ The Symfony Connect username in parenthesis allows to get more information - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Dmytro Borysovskyi (dmytr0) - - Bob van de Vijver (bobvandevijver) - Tomasz Kowalczyk (thunderer) - Artur Eshenbrener + - Soner Sayakci - Thomas Perez (scullwm) - Felix Labrecque - Yaroslav Kiliba - Terje Bråten - Renan Gonçalves (renan_saddam) - - Marco Petersen (ocrampete16) - Tarmo Leppänen (tarlepp) - Martin Auswöger - Robbert Klarenbeek (robbertkl) @@ -536,6 +538,7 @@ The Symfony Connect username in parenthesis allows to get more information - JhonnyL - hossein zolfi (ocean) - Clément Gautier (clementgautier) + - Koen Reiniers (koenre) - Dāvis Zālītis (k0d3r1s) - Sanpi - Eduardo Gulias (egulias) @@ -617,6 +620,7 @@ The Symfony Connect username in parenthesis allows to get more information - Valentin Jonovs (valentins-jonovs) - Bastien DURAND (deamon) - Jeanmonod David (jeanmonod) + - Christin Gruber (christingruber) - Andrey Sevastianov - Webnet team (webnet) - Urinbayev Shakhobiddin (shokhaa) @@ -666,6 +670,7 @@ The Symfony Connect username in parenthesis allows to get more information - Andrew M-Y (andr) - Krasimir Bosilkov (kbosilkov) - Marcin Michalski (marcinmichalski) + - Yoann RENARD (yrenard) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) - Niklas Keller @@ -676,7 +681,6 @@ The Symfony Connect username in parenthesis allows to get more information - Tim Goudriaan (codedmonkey) - Jonas Flodén (flojon) - AnneKir - - Soner Sayakci - Tobias Weichart - Miro Michalicka - Marcin Sikoń (marphi) @@ -692,7 +696,6 @@ The Symfony Connect username in parenthesis allows to get more information - Christian Wahler - Giso Stallenberg (gisostallenberg) - Gintautas Miselis - - Koen Reiniers (koenre) - Rob Bast - Roberto Espinoza (respinoza) - Pierre Rineau @@ -725,10 +728,13 @@ The Symfony Connect username in parenthesis allows to get more information - Jan van Thoor (janvt) - Gladhon - Joshua Nye + - Martin Kirilov (wucdbm) - Nathan Dench (ndenc2) + - Thibault Richard (t-richard) - Sebastian Bergmann - Miroslav Sustek - Pablo Díez (pablodip) + - SiD (plbsid) - Michel Roca (mroca) - Piotr Kugla (piku235) - Kevin McBride @@ -777,8 +783,10 @@ The Symfony Connect username in parenthesis allows to get more information - Norbert Orzechowicz (norzechowicz) - Denis Charrier (brucewouaigne) - Matthijs van den Bos (matthijs) + - Simon Podlipsky (simpod) - DemigodCode - Jaik Dean (jaikdean) + - Pavel Popov (metaer) - Lenard Palko - arai - Nils Adermann (naderman) @@ -824,6 +832,7 @@ The Symfony Connect username in parenthesis allows to get more information - Jeremy Benoist - Lenar Lõhmus - Daniël Brekelmans (dbrekelmans) + - Simon Heimberg (simon_heimberg) - Benjamin Laugueux (yzalis) - Zach Badgett (zachbadgett) - Aurélien Fredouelle @@ -860,7 +869,6 @@ The Symfony Connect username in parenthesis allows to get more information - Jules Matsounga (hyoa) - Quentin Dequippe (qdequippe) - khoptynskyi - - Christin Gruber (christingruber) - Jean-Christophe Cuvelier [Artack] - julien57 - Julien Montel (julienmgel) @@ -914,6 +922,7 @@ The Symfony Connect username in parenthesis allows to get more information - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) - Christophe Villeger (seragan) + - Hendrik Luup - Julien Fredon - Jacek Wilczyński (jacekwilczynski) - Xavier Leune (xleune) @@ -954,7 +963,6 @@ The Symfony Connect username in parenthesis allows to get more information - Mardari Dorel (dorumd) - Daisuke Ohata - Vincent Simonin - - Yoann RENARD (yrenard) - Alex Bogomazov (alebo) - maxime.steinhausser - Claus Due (namelesscoder) @@ -987,7 +995,6 @@ The Symfony Connect username in parenthesis allows to get more information - rtek - Benjamin Dos Santos - Jérémy Jarrié (gagnar) - - Martin Herndl (herndlm) - Tomas Javaisis - Ivan Grigoriev - Johann Saunier (prophet777) @@ -1058,7 +1065,6 @@ The Symfony Connect username in parenthesis allows to get more information - mohammadreza honarkhah - develop - flip111 - - Thibault Richard (t-richard) - VJ - RJ Garcia - Adam Wójs (awojs) @@ -1081,7 +1087,6 @@ The Symfony Connect username in parenthesis allows to get more information - Andrea Sprega (asprega) - Alexander Volochnev (exelenz) - Viktor Bajraktar (njutn95) - - SiD (plbsid) - Mbechezi Nawo - Michael Piecko - Toni Peric (tperic) @@ -1144,7 +1149,6 @@ The Symfony Connect username in parenthesis allows to get more information - michaelwilliams - Romain - Matěj Humpál - - Martin Kirilov - Pierre Grimaud (pgrimaud) - Alexandre Parent - 1emming @@ -1182,6 +1186,7 @@ The Symfony Connect username in parenthesis allows to get more information - Krzysiek Łabuś - Juraj Surman - Camille Dejoye + - Fabien S (bafs) - 1ma (jautenim) - Douglas Hammond (wizhippo) - Xavier Lacot (xavier) @@ -1204,7 +1209,6 @@ The Symfony Connect username in parenthesis allows to get more information - roromix - Dmitry Pigin (dotty) - Vincent Composieux (eko) - - Simon Podlipsky (simpod) - Jayson Xu (superjavason) - Hubert Lenoir (hubert_lenoir) - fago @@ -1248,6 +1252,7 @@ The Symfony Connect username in parenthesis allows to get more information - Aleksandar Jakovljevic (ajakov) - Laurent Bassin (lbassin) - Hamza Makraz (makraz) + - Tomasz Ignatiuk - andrey1s - Abhoryo - Fabian Vogler (fabian) @@ -1269,11 +1274,13 @@ The Symfony Connect username in parenthesis allows to get more information - Tony Malzhacker - Pchol - Mathieu MARCHOIS + - W0rma - Cyril Quintin (cyqui) - Cyrille Bourgois (cyrilleb) - Gerard van Helden (drm) - Johnny Peck (johnnypeck) - Marcos Rezende (rezehnde) + - Roman Anasal - Ivan Menshykov - David Romaní - Patrick Allaert @@ -1344,7 +1351,6 @@ The Symfony Connect username in parenthesis allows to get more information - Harry Walter (haswalt) - Johnson Page (jwpage) - Ruben Gonzalez (rubenruateltek) - - Simon Heimberg (simon_heimberg) - Michael Roterman (wtfzdotnet) - Arno Geurts - Adán Lobato (adanlobato) @@ -1412,6 +1418,7 @@ The Symfony Connect username in parenthesis allows to get more information - Antoine Bluchet (soyuka) - Patrick Kaufmann - Anton Dyshkant + - Paul Oms - Reece Fowell (reecefowell) - stefan.r - Guillaume Gammelin @@ -1558,6 +1565,7 @@ The Symfony Connect username in parenthesis allows to get more information - Maximilian Berghoff (electricmaxxx) - nacho - Piotr Antosik (antek88) + - Volker Killesreiter (ol0lll) - Vedran Mihočinec (v-m-i) - Sergey Novikov (s12v) - creiner @@ -1677,6 +1685,7 @@ The Symfony Connect username in parenthesis allows to get more information - rchoquet - gitlost - Taras Girnyk + - Dmitry Derepko - Jan Vernarsky - Amine Yakoubi - Eduardo García Sanz (coma) @@ -1686,7 +1695,9 @@ The Symfony Connect username in parenthesis allows to get more information - James Gilliland - fduch (fduch) - Juan Miguel Besada Vidal (soutlink) + - dlorek - Stuart Fyfe + - Carl Casbolt (carlcasbolt) - David de Boer (ddeboer) - Eno Mullaraj (emullaraj) - Nathan PAGE (nathix) @@ -1695,6 +1706,7 @@ The Symfony Connect username in parenthesis allows to get more information - arnaud (arnooo999) - Gilles Doge (gido) - Oscar Esteve (oesteve) + - Peter Potrowl - abulford - Philipp Kretzschmar - antograssiot @@ -1762,10 +1774,12 @@ The Symfony Connect username in parenthesis allows to get more information - Christian Rishøj - Patrick Berenschot - SuRiKmAn + - rtek - Jelte Steijaert (jelte) - David Négrier (moufmouf) - Quique Porta (quiqueporta) - Artem Oliynyk (artemoliynyk) + - Ben Roberts (benr77) - Andrea Quintino (dirk39) - Tomasz Szymczyk (karion) - Alex Vasilchenko @@ -1896,7 +1910,6 @@ The Symfony Connect username in parenthesis allows to get more information - Luis Galeas - Bogdan Scordaliu - Martin Pärtel - - Fabien S (bafs) - Daniel Rotter (danrot) - Frédéric Bouchery (fbouchery) - kylekatarnls (kylekatarnls) @@ -1921,6 +1934,7 @@ The Symfony Connect username in parenthesis allows to get more information - Guillaume BRETOU (guiguiboy) - Nikita Popov (nikic) - Carsten Nielsen (phreaknerd) + - Michael Olšavský - Jay Severson - Benny Born - Emirald Mateli @@ -2049,6 +2063,7 @@ The Symfony Connect username in parenthesis allows to get more information - Antonio Peric-Mazar (antonioperic) - César Suárez (csuarez) - Bjorn Twachtmann (dotbjorn) + - Wahyu Kristianto (kristories) - Tobias Genberg (lorceroth) - Nicolas Badey (nico-b) - Shane Preece (shane) @@ -2112,6 +2127,7 @@ The Symfony Connect username in parenthesis allows to get more information - Joni Halme - Matt Farmer - catch + - aetxebeste - siganushka - Alexandre Segura - Josef Cech @@ -2192,6 +2208,7 @@ The Symfony Connect username in parenthesis allows to get more information - David Stone - jjanvier - Julius Beckmann + - Ruben Jansen - shreypuranik - loru88 - Thibaut Salanon @@ -2261,6 +2278,7 @@ The Symfony Connect username in parenthesis allows to get more information - Alessio Baglio (ioalessio) - Johannes Müller (johmue) - Jordi Llonch (jordillonch) + - Jordi Sala Morales (jsala) - Mouad ZIANI (mouadziani) - Nicholas Ruunu (nicholasruunu) - Jeroen van den Nieuwenhuisen (nieuwenhuisen) @@ -2275,8 +2293,8 @@ The Symfony Connect username in parenthesis allows to get more information - alex - Nicole Cordes - Nicolas PHILIPPE - - Roman Anasal - Roman Orlov + - Simon Ackermann - VolCh - Alexey Popkov - Gijs Kunze @@ -2437,6 +2455,7 @@ The Symfony Connect username in parenthesis allows to get more information - Filipe Guerra - Jean Ragouin - Gerben Wijnja + - Emre YILMAZ - Rowan Manning - Per Modin - David Windell @@ -2521,6 +2540,7 @@ The Symfony Connect username in parenthesis allows to get more information - Bart Reunes (metalarend) - Muriel (metalmumu) - Michael Pohlers (mick_the_big) + - Misha Klomp (mishaklomp) - mlpo (mlpo) - Marek Šimeček (mssimi) - Dmitriy Tkachenko (neka) @@ -2598,6 +2618,7 @@ The Symfony Connect username in parenthesis allows to get more information - temperatur - misterx - Cas + - Vincent Godé - Dusan Kasan - Michael Steininger - Nardberjean @@ -2628,6 +2649,7 @@ The Symfony Connect username in parenthesis allows to get more information - Michel Bardelmeijer - Tomas Kmieliauskas - Ikko Ashimine + - Brad Jones - Billie Thompson - lol768 - jamogon @@ -2681,6 +2703,7 @@ The Symfony Connect username in parenthesis allows to get more information - James Michael DuPont - Kasperki - Tammy D + - Rodolfo Ruiz - Enrico - Ryan Rud - Ondrej Slinták @@ -2701,6 +2724,7 @@ The Symfony Connect username in parenthesis allows to get more information - Markus Staab - Pierre-Louis LAUNAY - djama + - Benjamin Rosenberger - Vladyslav Startsev - Michael Gwynne - Eduardo Conceição @@ -2717,6 +2741,7 @@ The Symfony Connect username in parenthesis allows to get more information - nsbx - Shude - Richard Hodgson + - Sven Fabricius - Ondřej Führer - Sema - Thorsten Hallwas @@ -2760,6 +2785,7 @@ The Symfony Connect username in parenthesis allows to get more information - Sam Anthony - Christian Stocker - Oussama Elgoumri + - Steve Marvell - Dawid Nowak - Lesnykh Ilia - sabruss @@ -2823,6 +2849,7 @@ The Symfony Connect username in parenthesis allows to get more information - Gerry Vandermaesen (gerryvdm) - Ghazy Ben Ahmed (ghazy) - Arash Tabriziyan (ghost098) + - Greg Szczotka (greg606) - ibasaw (ibasaw) - Vladislav Krupenkin (ideea) - Ilija Tovilo (ilijatovilo) From f8c1100c276ebb40faaf9f683b7c05c05df51a12 Mon Sep 17 00:00:00 2001 From: Fabien Potencier <fabien@potencier.org> Date: Mon, 30 Aug 2021 14:27:20 +0200 Subject: [PATCH 50/50] Update VERSION for 4.4.30 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 7956190d279d6..6c816aaf63d63 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 $freshCache = []; - public const VERSION = '4.4.30-DEV'; + public const VERSION = '4.4.30'; public const VERSION_ID = 40430; public const MAJOR_VERSION = 4; public const MINOR_VERSION = 4; public const RELEASE_VERSION = 30; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2022'; public const END_OF_LIFE = '11/2023';