From a12336a7cd5df9c2723eee62073bb9dd795a14d1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 Nov 2021 18:00:40 +0100 Subject: [PATCH 01/41] Bump Symfony version to 5.4.1 --- 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 656324a4df7e8..6a5546de95007 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.0'; - public const VERSION_ID = 50400; + public const VERSION = '5.4.1-DEV'; + public const VERSION_ID = 50401; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 0; - public const EXTRA_VERSION = ''; + public const RELEASE_VERSION = 1; + public const EXTRA_VERSION = 'DEV'; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025'; From c55bc0f9a326cca5b1930a6fe65d1cb90f789d5f Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 30 Nov 2021 16:02:12 +0100 Subject: [PATCH 02/41] =?UTF-8?q?[SecurityBundle]=C2=A0Fix=20invalid=20ref?= =?UTF-8?q?erence=20with=20`always=5Fauthenticate=5Fbefore=5Fgranting`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SecurityBundle/DependencyInjection/SecurityExtension.php | 2 +- .../Tests/DependencyInjection/SecurityExtensionTest.php | 2 +- .../Tests/Functional/app/StandardFormLogin/legacy_config.yml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 6fe970f366f3f..d937a54c43dfc 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -122,7 +122,7 @@ public function load(array $configs, ContainerBuilder $container) if ($config['always_authenticate_before_granting']) { $authorizationChecker = $container->getDefinition('security.authorization_checker'); $authorizationCheckerArgs = $authorizationChecker->getArguments(); - array_splice($authorizationCheckerArgs, 1, 0, [new Reference('security.authentication_manager')]); + array_splice($authorizationCheckerArgs, 1, 0, [new Reference('security.authentication.manager')]); $authorizationChecker->setArguments($authorizationCheckerArgs); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 8747273b9e9a6..5037bf2b93549 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -834,7 +834,7 @@ public function testLegacyAuthorizationManagerSignature() $args = $container->getDefinition('security.authorization_checker')->getArguments(); $this->assertEquals('security.token_storage', (string) $args[0]); - $this->assertEquals('security.authentication_manager', (string) $args[1]); + $this->assertEquals('security.authentication.manager', (string) $args[1]); $this->assertEquals('security.access.decision_manager', (string) $args[2]); $this->assertEquals('%security.access.always_authenticate_before_granting%', (string) $args[3]); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/legacy_config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/legacy_config.yml index e393772ae4b21..265e1d1c83d32 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/legacy_config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/legacy_config.yml @@ -2,6 +2,7 @@ imports: - { resource: ./legacy_base_config.yml } security: + always_authenticate_before_granting: true firewalls: default: anonymous: ~ From 369d9d7c8db282b39aab95c73ce44940602605ff Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Tue, 30 Nov 2021 12:58:03 +0100 Subject: [PATCH 03/41] [HttpClient] Fix handling error info in MockResponse --- .../HttpClient/Response/MockResponse.php | 4 +++ .../HttpClient/Tests/MockHttpClientTest.php | 31 +++---------------- .../Tests/Response/MockResponseTest.php | 11 +++++++ 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/HttpClient/Response/MockResponse.php b/src/Symfony/Component/HttpClient/Response/MockResponse.php index 8f5803202c1bf..c38a0a4f0cd6b 100644 --- a/src/Symfony/Component/HttpClient/Response/MockResponse.php +++ b/src/Symfony/Component/HttpClient/Response/MockResponse.php @@ -260,6 +260,10 @@ private static function readResponse(self $response, array $options, ResponseInt 'http_code' => $response->info['http_code'], ] + $info + $response->info; + if (null !== $response->info['error']) { + throw new TransportException($response->info['error']); + } + if (!isset($response->info['total_time'])) { $response->info['total_time'] = microtime(true) - $response->info['start_time']; } diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php index 75bf16d3e6c86..f97b0cbb363ff 100644 --- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php @@ -18,7 +18,6 @@ use Symfony\Component\HttpClient\Response\ResponseStream; use Symfony\Contracts\HttpClient\ChunkInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; -use Symfony\Contracts\HttpClient\ResponseInterface; class MockHttpClientTest extends HttpClientTestCase { @@ -141,16 +140,8 @@ protected function getHttpClient(string $testCase): HttpClientInterface break; case 'testDnsError': - $mock = $this->createMock(ResponseInterface::class); - $mock->expects($this->any()) - ->method('getStatusCode') - ->willThrowException(new TransportException('DSN error')); - $mock->expects($this->any()) - ->method('getInfo') - ->willReturn([]); - - $responses[] = $mock; - $responses[] = $mock; + $responses[] = $mockResponse = new MockResponse('', ['error' => 'DNS error']); + $responses[] = $mockResponse; break; case 'testToStream': @@ -164,12 +155,7 @@ protected function getHttpClient(string $testCase): HttpClientInterface break; case 'testTimeoutOnAccess': - $mock = $this->createMock(ResponseInterface::class); - $mock->expects($this->any()) - ->method('getHeaders') - ->willThrowException(new TransportException('Timeout')); - - $responses[] = $mock; + $responses[] = new MockResponse('', ['error' => 'Timeout']); break; case 'testAcceptHeader': @@ -231,16 +217,7 @@ protected function getHttpClient(string $testCase): HttpClientInterface break; case 'testMaxDuration': - $mock = $this->createMock(ResponseInterface::class); - $mock->expects($this->any()) - ->method('getContent') - ->willReturnCallback(static function (): void { - usleep(100000); - - throw new TransportException('Max duration was reached.'); - }); - - $responses[] = $mock; + $responses[] = new MockResponse('', ['error' => 'Max duration was reached.']); break; } diff --git a/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php b/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php index 2f389bcc80c79..c87c020ecac2c 100644 --- a/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php +++ b/src/Symfony/Component/HttpClient/Tests/Response/MockResponseTest.php @@ -4,6 +4,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpClient\Exception\JsonException; +use Symfony\Component\HttpClient\Exception\TransportException; use Symfony\Component\HttpClient\Response\MockResponse; /** @@ -83,4 +84,14 @@ public function toArrayErrors() 'message' => 'JSON content was expected to decode to an array, "integer" returned for "https://example.com/file.json".', ]; } + + public function testErrorIsTakenIntoAccountInInitialization() + { + $this->expectException(TransportException::class); + $this->expectExceptionMessage('ccc error'); + + MockResponse::fromRequest('GET', 'https://symfony.com', [], new MockResponse('', [ + 'error' => 'ccc error', + ]))->getStatusCode(); + } } From a6a3bced5dd48bec23ffb8b739f92b3e8c72831d Mon Sep 17 00:00:00 2001 From: Martins Sipenko Date: Tue, 30 Nov 2021 18:22:59 +0200 Subject: [PATCH 04/41] [Lock] create lock table if it does not exist --- src/Symfony/Component/Lock/Store/DoctrineDbalStore.php | 4 ++++ .../Component/Lock/Tests/Store/DoctrineDbalStoreTest.php | 1 - src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php b/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php index ead96843fbb78..1a94f3fc64711 100644 --- a/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php +++ b/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php @@ -14,6 +14,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Exception as DBALException; +use Doctrine\DBAL\Exception\TableNotFoundException; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Schema; use Symfony\Component\Lock\Exception\InvalidArgumentException; @@ -90,6 +91,9 @@ public function save(Key $key) ParameterType::STRING, ParameterType::STRING, ]); + } catch (TableNotFoundException $e) { + $this->createTable(); + $this->save($key); } catch (DBALException $e) { // the lock is already acquired. It could be us. Let's try to put off. $this->putOffExpiration($key, $this->initialTtl); diff --git a/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php index c20e2d3088111..6a89e49399b0c 100644 --- a/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/DoctrineDbalStoreTest.php @@ -70,7 +70,6 @@ public function testDsn(string $dsn, string $file = null) try { $store = new DoctrineDbalStore($dsn); - $store->createTable(); $store->save($key); $this->assertTrue($store->exists($key)); diff --git a/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php index 69968a2f11b80..dd15f0f1614b9 100644 --- a/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/PdoStoreTest.php @@ -84,7 +84,6 @@ public function testDsn(string $dsn, string $file = null) try { $store = new PdoStore($dsn); - $store->createTable(); $store->save($key); $this->assertTrue($store->exists($key)); From 60742265b8aa90af8cbb55bac63ee1cfba592118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20H=C3=A9lias?= Date: Wed, 1 Dec 2021 10:14:13 +0100 Subject: [PATCH 05/41] ResponseListener needs only 2 parameters --- src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php index 00b8d8aafbd5a..53613d3b5020c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.php @@ -70,7 +70,6 @@ ->args([ param('kernel.charset'), abstract_arg('The "set_content_language_from_locale" config value'), - param('kernel.enabled_locales'), ]) ->tag('kernel.event_subscriber') From 731712b29fad177649b78859c5522b99f99febb4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 29 Nov 2021 19:16:58 +0100 Subject: [PATCH 06/41] Update PR template --- .github/PULL_REQUEST_TEMPLATE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 62662f876fd3a..5e7092d385910 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 or 5.3 for bug fixes +| Branch? | 6.1 for features / 4.4, 5.3, 5.4 or 6.0 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no @@ -8,14 +8,14 @@ | License | MIT | Doc PR | symfony/symfony-docs#... From 70310ca9f3d3aebe02bca32f7cec9d40a3e8080b Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Tue, 30 Nov 2021 13:33:01 -0500 Subject: [PATCH 07/41] [DoctrineBridge] fix calling get_class on non-object --- .../Constraints/UniqueEntityValidatorTest.php | 27 +++++++++++++++++++ .../Constraints/UniqueEntityValidator.php | 5 ++++ 2 files changed, 32 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index c0945114c9c23..bc0041c20b64c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -37,6 +37,7 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\UnexpectedValueException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** @@ -821,6 +822,32 @@ public function testValidateUniquenessWithEmptyIterator($entity, $result) $this->assertNoViolation(); } + public function testValueMustBeObject() + { + $constraint = new UniqueEntity([ + 'message' => 'myMessage', + 'fields' => ['name'], + 'em' => self::EM_NAME, + ]); + + $this->expectException(UnexpectedValueException::class); + + $this->validator->validate('foo', $constraint); + } + + public function testValueCanBeNull() + { + $constraint = new UniqueEntity([ + 'message' => 'myMessage', + 'fields' => ['name'], + 'em' => self::EM_NAME, + ]); + + $this->validator->validate(null, $constraint); + + $this->assertNoViolation(); + } + public function resultWithEmptyIterator(): array { $entity = new SingleIntIdEntity(1, 'foo'); diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index df17e0eedd4c8..cce8cb9079723 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -16,6 +16,7 @@ use Symfony\Component\Validator\ConstraintValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; +use Symfony\Component\Validator\Exception\UnexpectedValueException; /** * Unique Entity Validator checks if one or a set of fields contain unique values. @@ -61,6 +62,10 @@ public function validate($entity, Constraint $constraint) return; } + if (!\is_object($entity)) { + throw new UnexpectedValueException($entity, 'object'); + } + if ($constraint->em) { $em = $this->registry->getManager($constraint->em); From bd4ace6cf9a3446c15f4b1bfa1d782e4ee4001ef Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 29 Nov 2021 19:01:24 +0100 Subject: [PATCH 08/41] [gha] swap the php versions we use in jobs --- .github/workflows/unit-tests.yml | 8 +- src/Symfony/Bridge/Doctrine/composer.json | 2 + .../Component/ErrorHandler/ErrorHandler.php | 4 +- .../Tests/phpt/exception_rethrown.phpt | 6 +- .../Tests/ConstraintValidatorTest.php | 4 +- src/Symfony/Component/Validator/composer.json | 2 +- .../VarDumper/Caster/ReflectionCaster.php | 20 ++-- .../Tests/Caster/ReflectionCasterTest.php | 98 +++---------------- 8 files changed, 43 insertions(+), 101 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 157f6462b4e67..9671caa0ed004 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -21,10 +21,10 @@ jobs: matrix: include: - php: '7.2' - - php: '8.1' - php: '7.4' - mode: high-deps - php: '8.0' + mode: high-deps + - php: '8.1' mode: low-deps - php: '8.2' mode: experimental @@ -172,14 +172,14 @@ jobs: exit 0 fi - (cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb) - if [[ "${{ matrix.mode }}" = low-deps ]]; then echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT'" exit 0 fi + (cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb) + # matrix.mode = high-deps echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP && $PHPUNIT$LEGACY'" || X=1 diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 79961033bc0a6..cce2609cf1a89 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -49,11 +49,13 @@ "conflict": { "doctrine/dbal": "<2.7", "doctrine/orm": "<2.6.3", + "doctrine/lexer": "<1.1", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/dependency-injection": "<3.4", "symfony/form": "<4.4", "symfony/http-kernel": "<4.3.7", "symfony/messenger": "<4.3", + "symfony/proxy-manager-bridge": "<4.4.19", "symfony/security-core": "<4.4", "symfony/validator": "<4.4.2|<5.0.2,>=5.0" }, diff --git a/src/Symfony/Component/ErrorHandler/ErrorHandler.php b/src/Symfony/Component/ErrorHandler/ErrorHandler.php index 9e523fd4c11f4..ceadcaf674fc6 100644 --- a/src/Symfony/Component/ErrorHandler/ErrorHandler.php +++ b/src/Symfony/Component/ErrorHandler/ErrorHandler.php @@ -609,7 +609,9 @@ public function handleException(\Throwable $exception) } $loggedErrors = $this->loggedErrors; - $this->loggedErrors = $exception === $handlerException ? 0 : $this->loggedErrors; + if ($exception === $handlerException) { + $this->loggedErrors &= ~$type; + } try { $this->handleException($handlerException); diff --git a/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt b/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt index 06540f4530121..be5ce6a5cdffa 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt +++ b/src/Symfony/Component/ErrorHandler/Tests/phpt/exception_rethrown.phpt @@ -16,7 +16,9 @@ if (true) { { public function log($level, $message, array $context = []): void { - echo 'LOG: ', $message, "\n"; + if (0 !== strpos($message, 'Deprecated: ')) { + echo 'LOG: ', $message, "\n"; + } } } } @@ -34,5 +36,5 @@ Exception {%S #message: "foo" #code: 0 #file: "%s" - #line: 25 + #line: 27 } diff --git a/src/Symfony/Component/Validator/Tests/ConstraintValidatorTest.php b/src/Symfony/Component/Validator/Tests/ConstraintValidatorTest.php index 6ca3eab41fd6e..aeaef472fb03d 100644 --- a/src/Symfony/Component/Validator/Tests/ConstraintValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/ConstraintValidatorTest.php @@ -15,13 +15,15 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; -final class ConstraintValidatorTest extends TestCase +class ConstraintValidatorTest extends TestCase { /** * @dataProvider formatValueProvider */ public function testFormatValue($expected, $value, $format = 0) { + \Locale::setDefault('en'); + $this->assertSame($expected, (new TestFormatValueConstraintValidator())->formatValueProxy($value, $format)); } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 0e84422e8deaf..72617c39cea09 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -41,7 +41,7 @@ "egulias/email-validator": "^2.1.10|^3" }, "conflict": { - "doctrine/lexer": "<1.0.2", + "doctrine/lexer": "<1.1", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/dependency-injection": "<3.4", "symfony/http-kernel": "<4.4", diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 819a618765dc5..2a74b25f21499 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -134,7 +134,7 @@ public static function castReflectionGenerator(\ReflectionGenerator $c, array $a array_unshift($trace, [ 'function' => 'yield', 'file' => $function->getExecutingFile(), - 'line' => $function->getExecutingLine() - 1, + 'line' => $function->getExecutingLine() - (int) (\PHP_VERSION_ID < 80100), ]); $trace[] = $frame; $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1); @@ -263,15 +263,17 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st unset($a[$prefix.'allowsNull']); } - try { - $a[$prefix.'default'] = $v = $c->getDefaultValue(); - if ($c->isDefaultValueConstant()) { - $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); - } - if (null === $v) { - unset($a[$prefix.'allowsNull']); + if ($c->isOptional()) { + try { + $a[$prefix.'default'] = $v = $c->getDefaultValue(); + if ($c->isDefaultValueConstant()) { + $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); + } + if (null === $v) { + unset($a[$prefix.'allowsNull']); + } + } catch (\ReflectionException $e) { } - } catch (\ReflectionException $e) { } return $a; diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index ff259b345793d..3dae54ce46b33 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -122,21 +122,8 @@ public function testReflectionParameter() { $var = new \ReflectionParameter(reflectionParameterFixture::class, 0); - if (\PHP_VERSION_ID < 80100) { - $this->assertDumpMatchesFormat( - <<<'EOTXT' -ReflectionParameter { - +name: "arg1" - position: 0 - typeHint: "Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass" - default: null -} -EOTXT - , $var - ); - } else { - $this->assertDumpMatchesFormat( - <<<'EOTXT' + $this->assertDumpMatchesFormat( + <<<'EOTXT' ReflectionParameter { +name: "arg1" position: 0 @@ -145,8 +132,7 @@ public function testReflectionParameter() } EOTXT , $var - ); - } + ); } public function testReflectionParameterScalar() @@ -468,38 +454,20 @@ public function testGenerator() $generator = new GeneratorDemo(); $generator = $generator->baz(); - if (\PHP_VERSION_ID < 80100) { - $expectedDump = <<<'EODUMP' + $expectedDump = <<<'EODUMP' Generator { this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} - executing: { + %s: { %sGeneratorDemo.php:14 { Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() › { › yield from bar(); › } } - } +%A} closed: false } EODUMP; - } else { - $expectedDump = <<<'EODUMP' -Generator { - this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} - trace: { - ./src/Symfony/Component/VarDumper/Tests/Fixtures/GeneratorDemo.php:13 { - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() - › public function baz() - › { - › yield from bar(); - } - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() {} - } - closed: false -} -EODUMP; - } $this->assertDumpMatchesFormat($expectedDump, $generator); @@ -507,69 +475,33 @@ public function testGenerator() break; } - if (\PHP_VERSION_ID < 80100) { - $expectedDump = <<<'EODUMP' + $expectedDump = <<<'EODUMP' array:2 [ 0 => ReflectionGenerator { this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} - trace: { - %s%eTests%eFixtures%eGeneratorDemo.php:9 { + %s: { + %s%eTests%eFixtures%eGeneratorDemo.php:%d { Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() - › { - › yield 1; - › } - } +%A › yield 1; +%A } %s%eTests%eFixtures%eGeneratorDemo.php:20 { …} %s%eTests%eFixtures%eGeneratorDemo.php:14 { …} - } +%A } closed: false } 1 => Generator { - executing: { - %sGeneratorDemo.php:10 { + %s: { + %s%eTests%eFixtures%eGeneratorDemo.php:%d { Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() › yield 1; › } › } - } - closed: false - } -] -EODUMP; - } else { - $expectedDump = <<<'EODUMP' -array:2 [ - 0 => ReflectionGenerator { - this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} - trace: { - %s%eTests%eFixtures%eGeneratorDemo.php:9 { - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() - › { - › yield 1; - › } - } - %s%eTests%eFixtures%eGeneratorDemo.php:20 { …} - %s%eTests%eFixtures%eGeneratorDemo.php:14 { …} - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() {} - } - closed: false - } - 1 => Generator { - trace: { - ./src/Symfony/Component/VarDumper/Tests/Fixtures/GeneratorDemo.php:9 { - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() - › { - › yield 1; - › } - } - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() {} - } +%A } closed: false } ] EODUMP; - } $r = new \ReflectionGenerator($generator); $this->assertDumpMatchesFormat($expectedDump, [$r, $r->getExecutingGenerator()]); From afab34d8ed9050878d209946f68a645d18b91bbc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 1 Dec 2021 15:17:12 +0100 Subject: [PATCH 09/41] [HttpKernel] fix sending Vary: Accept-Language when appropriate --- .../Component/HttpKernel/EventListener/LocaleListener.php | 1 + .../Component/HttpKernel/EventListener/ResponseListener.php | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php b/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php index 5d77377c6046b..f19e13649e988 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php @@ -70,6 +70,7 @@ private function setLocale(Request $request) $request->setLocale($locale); } elseif ($this->useAcceptLanguageHeader && $this->enabledLocales && ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales))) { $request->setLocale($preferredLanguage); + $request->attributes->set('_vary_by_language', true); } } diff --git a/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php b/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php index bb51c6dc0dbda..a4090159bb751 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ResponseListener.php @@ -50,6 +50,9 @@ public function onKernelResponse(ResponseEvent $event) if ($this->addContentLanguageHeader && !$response->isInformational() && !$response->isEmpty() && !$response->headers->has('Content-Language')) { $response->headers->set('Content-Language', $event->getRequest()->getLocale()); + } + + if ($event->getRequest()->attributes->get('_vary_by_language')) { $response->setVary('Accept-Language', false); } From 3f710c2e5eac0b1d19ff4c2c99012eff367becc8 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Tue, 30 Nov 2021 21:15:45 +0100 Subject: [PATCH 10/41] [HttpFoundation] fix SessionHandlerFactory using connections --- .../Storage/Handler/SessionHandlerFactory.php | 2 +- .../Handler/SessionHandlerFactoryTest.php | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/SessionHandlerFactory.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/SessionHandlerFactory.php index 0f1ce5c2b8ecd..f3f7b201d9dea 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/SessionHandlerFactory.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/SessionHandlerFactory.php @@ -30,7 +30,7 @@ public static function createHandler($connection): AbstractSessionHandler throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a string or a connection object, "%s" given.', __METHOD__, get_debug_type($connection))); } - if ($options = parse_url($connection)) { + if ($options = \is_string($connection) ? parse_url($connection) : false) { parse_str($options['query'] ?? '', $options); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php index 46d6cd40151d5..9f06a7c8675da 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/SessionHandlerFactoryTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\SessionHandlerFactory; use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; @@ -28,7 +29,7 @@ class SessionHandlerFactoryTest extends TestCase /** * @dataProvider provideConnectionDSN */ - public function testCreateHandler(string $connectionDSN, string $expectedPath, string $expectedHandlerType) + public function testCreateFileHandler(string $connectionDSN, string $expectedPath, string $expectedHandlerType) { $handler = SessionHandlerFactory::createHandler($connectionDSN); @@ -45,4 +46,32 @@ public function provideConnectionDSN(): array 'native file handler using provided save_path' => ['connectionDSN' => 'file://'.$base.'/session/storage', 'expectedPath' => $base.'/session/storage', 'expectedHandlerType' => StrictSessionHandler::class], ]; } + + /** + * @requires extension redis + */ + public function testCreateRedisHandlerFromConnectionObject() + { + $handler = SessionHandlerFactory::createHandler($this->createMock(\Redis::class)); + $this->assertInstanceOf(RedisSessionHandler::class, $handler); + } + + /** + * @requires extension redis + */ + public function testCreateRedisHandlerFromDsn() + { + $handler = SessionHandlerFactory::createHandler('redis://localhost?prefix=foo&ttl=3600&ignored=bar'); + $this->assertInstanceOf(RedisSessionHandler::class, $handler); + + $reflection = new \ReflectionObject($handler); + + $prefixProperty = $reflection->getProperty('prefix'); + $prefixProperty->setAccessible(true); + $this->assertSame('foo', $prefixProperty->getValue($handler)); + + $ttlProperty = $reflection->getProperty('ttl'); + $ttlProperty->setAccessible(true); + $this->assertSame('3600', $ttlProperty->getValue($handler)); + } } From 366cb1ad3aa4de4698c79fe4d065fd3fb6257de6 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Tue, 30 Nov 2021 13:06:07 +0100 Subject: [PATCH 11/41] Avoid duplicated session listener registration in tests --- .../DependencyInjection/FrameworkExtension.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 9b761dbdd3934..17950515dd922 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -350,6 +350,11 @@ public function load(array $configs, ContainerBuilder $container) $this->sessionConfigEnabled = true; $this->registerSessionConfiguration($config['session'], $container, $loader); + if (!empty($config['test'])) { + // test listener will replace the existing session listener + // as we are aliasing to avoid duplicated registered events + $container->setAlias('session_listener', 'test.session.listener'); + } } elseif (!empty($config['test'])) { $container->removeDefinition('test.session.listener'); } From 0e56bf22e2ccd91bba8653ae23754cc0252cb3e9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 1 Dec 2021 16:43:39 +0100 Subject: [PATCH 12/41] Fix low-deps --- .github/workflows/unit-tests.yml | 3 +++ src/Symfony/Bridge/Doctrine/composer.json | 1 + src/Symfony/Component/Lock/composer.json | 1 - src/Symfony/Component/Runtime/composer.json | 6 +++--- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 9671caa0ed004..2442e0caf7b92 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -179,12 +179,14 @@ jobs: fi (cd src/Symfony/Component/HttpFoundation; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb) + (cd src/Symfony/Component/Lock; cp composer.json composer.bak; composer require --dev --no-update mongodb/mongodb) # matrix.mode = high-deps echo "$COMPONENTS" | xargs -n1 | parallel -j +3 "_run_tests {} 'cd {} && $COMPOSER_UP && $PHPUNIT$LEGACY'" || X=1 # get a list of the patched components (relies on .github/build-packages.php being called in the previous step) (cd src/Symfony/Component/HttpFoundation; mv composer.bak composer.json) + (cd src/Symfony/Component/Lock; mv composer.bak composer.json) PATCHED_COMPONENTS=$(git diff --name-only src/ | grep composer.json || true) # for 5.4 LTS, checkout and test previous major with the patched components (only for patched components) @@ -198,6 +200,7 @@ jobs: git checkout -m FETCH_HEAD PATCHED_COMPONENTS=$(echo "$PATCHED_COMPONENTS" | xargs dirname | xargs -n1 -I{} bash -c "[ -e '{}/phpunit.xml.dist' ] && echo '{}'" | sort || true) (cd src/Symfony/Component/HttpFoundation; composer require --dev --no-update mongodb/mongodb) + (cd src/Symfony/Component/Lock; composer require --dev --no-update mongodb/mongodb) if [[ $PATCHED_COMPONENTS ]]; then echo "::group::install phpunit" ./phpunit install diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 7bc4feb945a08..1ead9f0eb4b06 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -52,6 +52,7 @@ }, "conflict": { "doctrine/dbal": "<2.10", + "doctrine/lexer": "<1.1", "doctrine/orm": "<2.7.3", "phpunit/phpunit": "<5.4.3", "symfony/dependency-injection": "<4.4", diff --git a/src/Symfony/Component/Lock/composer.json b/src/Symfony/Component/Lock/composer.json index 2c4c81c96df40..134ffb57abedb 100644 --- a/src/Symfony/Component/Lock/composer.json +++ b/src/Symfony/Component/Lock/composer.json @@ -23,7 +23,6 @@ }, "require-dev": { "doctrine/dbal": "^2.10|^3.0", - "mongodb/mongodb": "~1.1", "predis/predis": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/Runtime/composer.json b/src/Symfony/Component/Runtime/composer.json index 668130cdbc2e2..9c8e19ded6d3e 100644 --- a/src/Symfony/Component/Runtime/composer.json +++ b/src/Symfony/Component/Runtime/composer.json @@ -21,10 +21,10 @@ }, "require-dev": { "composer/composer": "^1.0.2|^2.0", - "symfony/console": "^4.4|^5", + "symfony/console": "^4.4.30|^5.3.7", "symfony/dotenv": "^5.1", - "symfony/http-foundation": "^4.4|^5", - "symfony/http-kernel": "^4.4|^5" + "symfony/http-foundation": "^4.4.30|^5.3.7", + "symfony/http-kernel": "^4.4.30|^5.3.7" }, "conflict": { "symfony/dotenv": "<5.1" From b2fe0e0f976dbb55e1acc05fa3fff519d515cc7d Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 1 Dec 2021 10:04:50 +0100 Subject: [PATCH 13/41] [DependencyInjection] Skip parameter attribute configurators in AttributeAutoconfigurationPass if we can't get the constructor reflector --- .../AttributeAutoconfigurationPass.php | 19 ++++++++++++++----- .../Tests/Compiler/IntegrationTest.php | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php index f5094996d949f..4db7185cf534b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * @author Alexander M. Turek @@ -99,11 +100,19 @@ protected function processValue($value, bool $isRoot = false) } } - if ($this->parameterAttributeConfigurators && $constructorReflector = $this->getConstructor($value, false)) { - foreach ($constructorReflector->getParameters() as $parameterReflector) { - foreach ($parameterReflector->getAttributes() as $attribute) { - if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) { - $configurator($conditionals, $attribute->newInstance(), $parameterReflector); + if ($this->parameterAttributeConfigurators) { + try { + $constructorReflector = $this->getConstructor($value, false); + } catch (RuntimeException $e) { + $constructorReflector = null; + } + + if ($constructorReflector) { + foreach ($constructorReflector->getParameters() as $parameterReflector) { + foreach ($parameterReflector->getAttributes() as $attribute) { + if ($configurator = $this->parameterAttributeConfigurators[$attribute->getName()] ?? null) { + $configurator($conditionals, $attribute->newInstance(), $parameterReflector); + } } } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php index 1e5df4879673e..6624f74901320 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php @@ -976,6 +976,11 @@ static function (ChildDefinition $definition, CustomParameterAttribute $attribut ->setPublic(true) ->setAutoconfigured(true); + $container->register('failing_factory', \stdClass::class); + $container->register('ccc', TaggedService4::class) + ->setFactory([new Reference('failing_factory'), 'create']) + ->setAutoconfigured(true); + $collector = new TagCollector(); $container->addCompilerPass($collector); @@ -996,6 +1001,17 @@ static function (ChildDefinition $definition, CustomParameterAttribute $attribut ['property' => 'name'], ['someAttribute' => 'on name', 'priority' => 0, 'property' => 'name'], ], + 'ccc' => [ + ['class' => TaggedService4::class], + ['method' => 'fooAction'], + ['someAttribute' => 'on fooAction', 'priority' => 0, 'method' => 'fooAction'], + ['parameter' => 'param1'], + ['someAttribute' => 'on param1 in fooAction', 'priority' => 0, 'parameter' => 'param1'], + ['method' => 'barAction'], + ['someAttribute' => 'on barAction', 'priority' => 0, 'method' => 'barAction'], + ['property' => 'name'], + ['someAttribute' => 'on name', 'priority' => 0, 'property' => 'name'], + ], ], $collector->collectedTags); } From 770425c75abbb875f58f5bfdc3903dfee05afcc9 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Wed, 1 Dec 2021 17:25:24 +0100 Subject: [PATCH 14/41] Prevent infinite nesting of lazy `ObjectManager` instances when `ObjectManager` is reset This patch ensures that the `ObjectManager` that the `Symfony\Bridge\Doctrine\ManagerRegistry` replaces during `Symfony\Bridge\Doctrine\ManagerRegistry#resetService()` operations is a fresh non-lazy service. Before this change, `Symfony\Bridge\Doctrine\ManagerRegistry#resetService()` would replace the initialization of the lazy proxy with a new service each time, but that service being lazy, this led to an additional proxy nesting level at each service reset call. That leads to general issues around memory reliability, stack trace nesting (and therefore bigger logged traces) and potentially even stack overflow problems, when running with XDebug. The problem seems to only apply when the `symfony/dependency-injection` `Container` is compiled as a set of small factory files: that's because each generated factory has a boolean flag that indicates whether a lazy or non-lazy version of a service is requested, as introduced in the original implementation at https://github.com/symfony/symfony/pull/7890 --- .../Bridge/Doctrine/ManagerRegistry.php | 2 +- .../Doctrine/Tests/ManagerRegistryTest.php | 93 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index 2139562dedbaf..0ed055fec64b7 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -62,7 +62,7 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { $name = $this->aliases[$name]; } if (isset($this->fileMap[$name])) { - $wrappedInstance = $this->load($this->fileMap[$name]); + $wrappedInstance = $this->load($this->fileMap[$name], false); } else { $method = $this->methodMap[$name] ?? 'get'.strtr($name, $this->underscoreMap).'Service'; // BC with DI v3.4 $wrappedInstance = $this->{$method}(false); diff --git a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php index a004935a6afdc..dcdc4ce6360fc 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php @@ -12,8 +12,15 @@ namespace Symfony\Bridge\Doctrine\Tests; use PHPUnit\Framework\TestCase; +use ProxyManager\Proxy\LazyLoadingInterface; +use ProxyManager\Proxy\ValueHolderInterface; use Symfony\Bridge\Doctrine\ManagerRegistry; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Bridge\ProxyManager\Tests\LazyProxy\Dumper\PhpDumperTest; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\Filesystem\Filesystem; class ManagerRegistryTest extends TestCase { @@ -39,6 +46,92 @@ public function testResetService() $this->assertSame($foo, $container->get('foo')); $this->assertObjectNotHasAttribute('bar', $foo); } + + /** + * When performing an entity manager lazy service reset, the reset operations may re-use the container + * to create a "fresh" service: when doing so, it can happen that the "fresh" service is itself a proxy. + * + * Because of that, the proxy will be populated with a wrapped value that is itself a proxy: repeating + * the reset operation keeps increasing this nesting until the application eventually runs into stack + * overflow or memory overflow operations, which can happen for long-running processes that rely on + * services that are reset very often. + */ + public function testResetServiceWillNotNestFurtherLazyServicesWithinEachOther() + { + // This test scenario only applies to containers composed as a set of generated sources + $this->dumpLazyServiceProjectAsFilesServiceContainer(); + + /** @var ContainerInterface $container */ + $container = new \LazyServiceProjectAsFilesServiceContainer(); + + $registry = new TestManagerRegistry( + 'irrelevant', + [], + ['defaultManager' => 'foo'], + 'irrelevant', + 'defaultManager', + 'irrelevant' + ); + $registry->setTestContainer($container); + + $service = $container->get('foo'); + + self::assertInstanceOf(\stdClass::class, $service); + self::assertInstanceOf(LazyLoadingInterface::class, $service); + self::assertInstanceOf(ValueHolderInterface::class, $service); + self::assertFalse($service->isProxyInitialized()); + + $service->initializeProxy(); + + self::assertTrue($container->initialized('foo')); + self::assertTrue($service->isProxyInitialized()); + + $registry->resetManager(); + $service->initializeProxy(); + + $wrappedValue = $service->getWrappedValueHolderValue(); + self::assertInstanceOf(\stdClass::class, $wrappedValue); + self::assertNotInstanceOf(LazyLoadingInterface::class, $wrappedValue); + self::assertNotInstanceOf(ValueHolderInterface::class, $wrappedValue); + } + + /** @return void */ + private function dumpLazyServiceProjectAsFilesServiceContainer() + { + if (class_exists(\LazyServiceProjectAsFilesServiceContainer::class, false)) { + return; + } + + $container = new ContainerBuilder(); + + $container->register('foo', \stdClass::class) + ->setPublic(true) + ->setLazy(true); + $container->compile(); + + $fileSystem = new Filesystem(); + + $temporaryPath = $fileSystem->tempnam(sys_get_temp_dir(), 'symfonyManagerRegistryTest'); + $fileSystem->remove($temporaryPath); + $fileSystem->mkdir($temporaryPath); + + $dumper = new PhpDumper($container); + + $dumper->setProxyDumper(new ProxyDumper()); + $containerFiles = $dumper->dump([ + 'class' => 'LazyServiceProjectAsFilesServiceContainer', + 'as_files' => true, + ]); + + array_walk( + $containerFiles, + static function (string $containerSources, string $fileName) use ($temporaryPath): void { + (new Filesystem())->dumpFile($temporaryPath.'/'.$fileName, $containerSources); + } + ); + + require $temporaryPath.'/LazyServiceProjectAsFilesServiceContainer.php'; + } } class TestManagerRegistry extends ManagerRegistry From a7c771250ae7ec97e11fbb4363b85ccd0789f298 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 2 Dec 2021 09:27:42 +0100 Subject: [PATCH 15/41] Tweak bug report template --- .github/ISSUE_TEMPLATE/1_Bug_report.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml index 5518d4e4ad79d..241c1f779bfaa 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml @@ -14,7 +14,7 @@ body: id: description attributes: label: Description - description: A clear and consise description of the problem + description: A clear and concise description of the problem validations: required: true - type: textarea @@ -22,15 +22,21 @@ body: attributes: label: How to reproduce description: | - Code and/or config needed to reproduce the problem. - If it's a complex bug, create a "bug reproducer" as explained in https://symfony.com/doc/current/contributing/code/reproducer.html + ⚠️ This is the most important part of the report ⚠️ + Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix. + Please, take the time to show us some code and/or config that is needed for others to reproduce the problem easily. + Most of the time, creating a "bug reproducer" as explained in the URL below is the best way to help us + and increases the chances someone will have a look at it: + https://symfony.com/doc/current/contributing/code/reproducer.html validations: required: true - type: textarea id: possible-solution attributes: label: Possible Solution - description: "Optional: only if you have suggestions on a fix/reason for the bug" + description: | + Optional: only if you have suggestions on a fix/reason for the bug + Don't hesitate to create a pull request with your solution, it helps get faster feedback. - type: textarea id: additional-context attributes: From 620d06c774ce148829ef6a0f32433567a0ccc1ac Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 2 Dec 2021 14:32:36 +0100 Subject: [PATCH 16/41] Remove unneeded files --- .github/ISSUE_TEMPLATE/1_Bug_report.md | 22 --------------------- .github/ISSUE_TEMPLATE/2_Feature_request.md | 12 ----------- 2 files changed, 34 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/1_Bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/2_Feature_request.md diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md deleted file mode 100644 index aef16611e0f77..0000000000000 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: 🐛 Bug Report -about: ⚠️ See below for security reports -labels: Bug - ---- - -**Symfony version(s) affected**: x.y.z - -**Description** - - -**How to reproduce** - - -**Possible Solution** - - -**Additional context** - diff --git a/.github/ISSUE_TEMPLATE/2_Feature_request.md b/.github/ISSUE_TEMPLATE/2_Feature_request.md deleted file mode 100644 index 908c5ee52664d..0000000000000 --- a/.github/ISSUE_TEMPLATE/2_Feature_request.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: 🚀 Feature Request -about: RFC and ideas for new features and improvements - ---- - -**Description** - - -**Example** - From 53cfbfda640ea7c11da7076a6e1f8e3ffc709834 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 2 Dec 2021 14:45:50 +0100 Subject: [PATCH 17/41] Add missing files from 5.3 --- .github/ISSUE_TEMPLATE/3_Support_question.md | 11 +++++++++++ .github/ISSUE_TEMPLATE/4_Documentation_issue.md | 10 ++++++++++ 2 files changed, 21 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/3_Support_question.md create mode 100644 .github/ISSUE_TEMPLATE/4_Documentation_issue.md diff --git a/.github/ISSUE_TEMPLATE/3_Support_question.md b/.github/ISSUE_TEMPLATE/3_Support_question.md new file mode 100644 index 0000000000000..9480710c15655 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3_Support_question.md @@ -0,0 +1,11 @@ +--- +name: ⛔ Support Question +about: See https://symfony.com/support for questions about using Symfony and its components + +--- + +We use GitHub issues only to discuss about Symfony bugs and new features. For +this kind of questions about using Symfony or third-party bundles, please use +any of the support alternatives shown in https://symfony.com/support + +Thanks! diff --git a/.github/ISSUE_TEMPLATE/4_Documentation_issue.md b/.github/ISSUE_TEMPLATE/4_Documentation_issue.md new file mode 100644 index 0000000000000..0855c3c5f1e12 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/4_Documentation_issue.md @@ -0,0 +1,10 @@ +--- +name: ⛔ Documentation Issue +about: See https://github.com/symfony/symfony-docs/issues for documentation issues + +--- + +Symfony Documentation has its own dedicated repository. Please open your +documentation-related issue at https://github.com/symfony/symfony-docs/issues + +Thanks! From 058720f4ed8c69b660932c1f52bc8f8ca9c80dcd Mon Sep 17 00:00:00 2001 From: gjuric Date: Thu, 2 Dec 2021 10:40:44 +0100 Subject: [PATCH 18/41] Document deprecations in Security Tokens --- UPGRADE-5.4.md | 16 ++++++++++++++++ UPGRADE-6.0.md | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/UPGRADE-5.4.md b/UPGRADE-5.4.md index a2ce35807705d..2f5ca06682a12 100644 --- a/UPGRADE-5.4.md +++ b/UPGRADE-5.4.md @@ -170,3 +170,19 @@ Security * Deprecate passing the strategy as string to `AccessDecisionManager`, pass an instance of `AccessDecisionStrategyInterface` instead * Flag `AccessDecisionManager` as `@final` + * Deprecate passing `$credentials` to `PreAuthenticatedToken`, + `SwitchUserToken` and `UsernamePasswordToken`: + + Before: + ```php + $token = new UsernamePasswordToken($user, $credentials, $firewallName, $roles); + $token = new PreAuthenticatedToken($user, $credentials, $firewallName, $roles); + $token = new SwitchUserToken($user, $credentials, $firewallName, $roles, $originalToken); + ``` + + After: + ```php + $token = new UsernamePasswordToken($user, $firewallName, $roles); + $token = new PreAuthenticatedToken($user, $firewallName, $roles); + $token = new SwitchUserToken($user, $firewallName, $roles, $originalToken); + ``` diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 10c9dcc9199e3..0f3b9e29bbd77 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -408,6 +408,22 @@ Security ``` * `AccessDecisionManager` does not accept strings as strategy anymore, pass an instance of `AccessDecisionStrategyInterface` instead + * Removed the `$credentials` argument of `PreAuthenticatedToken`, + `SwitchUserToken` and `UsernamePasswordToken`: + + Before: + ```php + $token = new UsernamePasswordToken($user, $credentials, $firewallName, $roles); + $token = new PreAuthenticatedToken($user, $credentials, $firewallName, $roles); + $token = new SwitchUserToken($user, $credentials, $firewallName, $roles, $originalToken); + ``` + + After: + ```php + $token = new UsernamePasswordToken($user, $firewallName, $roles); + $token = new PreAuthenticatedToken($user, $firewallName, $roles); + $token = new SwitchUserToken($user, $firewallName, $roles, $originalToken); + ``` SecurityBundle -------------- From c3374d276aba6f3c49919c4a7ab9a2c1dbac07bf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 2 Dec 2021 14:54:19 +0100 Subject: [PATCH 19/41] Fix description that does not work well --- .github/ISSUE_TEMPLATE/1_Bug_report.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml index 241c1f779bfaa..ef0f72c794278 100644 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/1_Bug_report.yaml @@ -1,5 +1,5 @@ name: 🐛 Bug Report -description: ⚠️ See below for security reports +description: ⚠️ NEVER report security issues, read https://symfony.com/security instead labels: Bug body: From 10b3b6870e892889b1a6f4ac85fddcd0a35c1b2f Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Thu, 2 Dec 2021 15:49:54 +0100 Subject: [PATCH 20/41] Use external links instead of fake issue templates --- .github/ISSUE_TEMPLATE/3_Support_question.md | 11 ----------- .github/ISSUE_TEMPLATE/4_Documentation_issue.md | 10 ---------- .github/ISSUE_TEMPLATE/config.yml | 8 ++++++++ 3 files changed, 8 insertions(+), 21 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/3_Support_question.md delete mode 100644 .github/ISSUE_TEMPLATE/4_Documentation_issue.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/3_Support_question.md b/.github/ISSUE_TEMPLATE/3_Support_question.md deleted file mode 100644 index 9480710c15655..0000000000000 --- a/.github/ISSUE_TEMPLATE/3_Support_question.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -name: ⛔ Support Question -about: See https://symfony.com/support for questions about using Symfony and its components - ---- - -We use GitHub issues only to discuss about Symfony bugs and new features. For -this kind of questions about using Symfony or third-party bundles, please use -any of the support alternatives shown in https://symfony.com/support - -Thanks! diff --git a/.github/ISSUE_TEMPLATE/4_Documentation_issue.md b/.github/ISSUE_TEMPLATE/4_Documentation_issue.md deleted file mode 100644 index 0855c3c5f1e12..0000000000000 --- a/.github/ISSUE_TEMPLATE/4_Documentation_issue.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: ⛔ Documentation Issue -about: See https://github.com/symfony/symfony-docs/issues for documentation issues - ---- - -Symfony Documentation has its own dedicated repository. Please open your -documentation-related issue at https://github.com/symfony/symfony-docs/issues - -Thanks! diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000..34227566ed84a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Support Question + url: https://symfony.com/support + about: We use GitHub issues only to discuss about Symfony bugs and new features. For this kind of questions about using Symfony or third-party bundles, please use any of the support alternatives shown in https://symfony.com/support + - name: Documentation Issue + url: https://github.com/symfony/symfony-docs/issues + about: Symfony Documentation has its own dedicated repository. From 47c3ed317f247d4c99ef54b5b0979e673c6f56b6 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 2 Dec 2021 17:04:53 +0100 Subject: [PATCH 21/41] Don't rely on deprecated strategy constants --- .../SecurityBundle/Resources/views/Collector/security.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 0771f15a803b7..91e75ce0c5347 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -407,7 +407,7 @@ {% for voter_detail in decision.voter_details %} {{ profiler_dump(voter_detail['class']) }} - {% if collector.voterStrategy == constant('Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManager::STRATEGY_UNANIMOUS') %} + {% if collector.voterStrategy == 'unanimous' %} attribute {{ voter_detail['attributes'][0] }} {% endif %} From e044b179d0d118348f5741c47ccf02661d16748b Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Thu, 2 Dec 2021 18:38:19 +0100 Subject: [PATCH 22/41] Fix compatibility with symfony/security-core 6.x --- src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php | 5 ++++- .../Tests/Controller/AbstractControllerTest.php | 12 +++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php index 7d4475a7e21ca..c5bad9c4e5185 100644 --- a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php +++ b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php @@ -123,7 +123,10 @@ public function loginUser(object $user, string $firewallContext = 'main'): self } $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext); - $token->setAuthenticated(true); + // @deprecated since Symfony 5.4 + if (method_exists($token, 'setAuthenticated')) { + $token->setAuthenticated(true); + } $container = $this->getContainer(); $container->get('security.untracked_token_storage')->setToken($token); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index c6353acdb75c7..c24738545d343 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -138,7 +138,12 @@ public function testForward() public function testGetUser() { $user = new InMemoryUser('user', 'pass'); - $token = new UsernamePasswordToken($user, 'pass', 'default', ['ROLE_USER']); + if (method_exists(UsernamePasswordToken::class, 'setAuthenticated')) { + // @deprecated since Symfony 5.4 + $token = new UsernamePasswordToken($user, 'pass', 'default', ['ROLE_USER']); + } else { + $token = new UsernamePasswordToken($user, 'default', ['ROLE_USER']); + } $controller = $this->createController(); $controller->setContainer($this->getContainerWithTokenStorage($token)); @@ -148,6 +153,11 @@ public function testGetUser() public function testGetUserAnonymousUserConvertedToNull() { + // @deprecated since Symfony 5.4 + if (!class_exists(AnonymousToken::class)) { + $this->markTestSkipped('This test requires "symfony/security-core" <6.0.'); + } + $token = new AnonymousToken('default', 'anon.'); $controller = $this->createController(); From 481cb9e1e42a273114f6fbc347e538e902ba1664 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Fri, 3 Dec 2021 09:00:22 +0100 Subject: [PATCH 23/41] Fix merge --- .../Tests/Controller/AbstractControllerTest.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index 6697e96a37d9a..9a5c5510ce14e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -138,12 +138,7 @@ public function testForward() public function testGetUser() { $user = new InMemoryUser('user', 'pass'); - if (method_exists(UsernamePasswordToken::class, 'setAuthenticated')) { - // @deprecated since Symfony 5.4 - $token = new UsernamePasswordToken($user, 'pass', 'default', ['ROLE_USER']); - } else { - $token = new UsernamePasswordToken($user, 'default', ['ROLE_USER']); - } + $token = new UsernamePasswordToken($user, 'default', ['ROLE_USER']); $controller = $this->createController(); $controller->setContainer($this->getContainerWithTokenStorage($token)); @@ -156,11 +151,6 @@ public function testGetUser() */ public function testGetUserAnonymousUserConvertedToNull() { - // @deprecated since Symfony 5.4 - if (!class_exists(AnonymousToken::class)) { - $this->markTestSkipped('This test requires "symfony/security-core" <6.0.'); - } - $token = new AnonymousToken('default', 'anon.'); $controller = $this->createController(); From 3c1c8542d1493f1f6c6bac6d49548aec963c7664 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 3 Dec 2021 12:31:53 +0100 Subject: [PATCH 24/41] Remove return void PHPDoc in test --- src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php index dcdc4ce6360fc..dd7dabcc87db1 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php @@ -95,7 +95,6 @@ public function testResetServiceWillNotNestFurtherLazyServicesWithinEachOther() self::assertNotInstanceOf(ValueHolderInterface::class, $wrappedValue); } - /** @return void */ private function dumpLazyServiceProjectAsFilesServiceContainer() { if (class_exists(\LazyServiceProjectAsFilesServiceContainer::class, false)) { From 80a9c9fa403ebf7bdb3a87d0e4b69d4c1ee05763 Mon Sep 17 00:00:00 2001 From: Hugo Alliaume Date: Thu, 2 Dec 2021 13:32:05 +0100 Subject: [PATCH 25/41] [Translation][Loco] Make http requests synchronous when reading the Loco API --- .../Translation/Bridge/Loco/LocoProvider.php | 54 ++++++++----------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php b/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php index 3882176d8d54a..cea4121f7364e 100644 --- a/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php +++ b/src/Symfony/Component/Translation/Bridge/Loco/LocoProvider.php @@ -92,47 +92,37 @@ public function read(array $domains, array $locales): TranslatorBag { $domains = $domains ?: ['*']; $translatorBag = new TranslatorBag(); - $responses = []; foreach ($locales as $locale) { foreach ($domains as $domain) { - $responses[] = [ - 'response' => $this->client->request('GET', sprintf('export/locale/%s.xlf', rawurlencode($locale)), [ - 'query' => [ - 'filter' => $domain, - 'status' => 'translated', - ], - ]), - 'locale' => $locale, - 'domain' => $domain, - ]; - } - } - - foreach ($responses as $response) { - $locale = $response['locale']; - $domain = $response['domain']; - $response = $response['response']; + // Loco forbids concurrent requests, so the requests must be synchronous in order to prevent "429 Too Many Requests" errors. + $response = $this->client->request('GET', sprintf('export/locale/%s.xlf', rawurlencode($locale)), [ + 'query' => [ + 'filter' => $domain, + 'status' => 'translated', + ], + ]); + + if (404 === $response->getStatusCode()) { + $this->logger->warning(sprintf('Locale "%s" for domain "%s" does not exist in Loco.', $locale, $domain)); + continue; + } - if (404 === $response->getStatusCode()) { - $this->logger->warning(sprintf('Locale "%s" for domain "%s" does not exist in Loco.', $locale, $domain)); - continue; - } + $responseContent = $response->getContent(false); - $responseContent = $response->getContent(false); + if (200 !== $response->getStatusCode()) { + throw new ProviderException('Unable to read the Loco response: '.$responseContent, $response); + } - if (200 !== $response->getStatusCode()) { - throw new ProviderException('Unable to read the Loco response: '.$responseContent, $response); - } + $locoCatalogue = $this->loader->load($responseContent, $locale, $domain); + $catalogue = new MessageCatalogue($locale); - $locoCatalogue = $this->loader->load($responseContent, $locale, $domain); - $catalogue = new MessageCatalogue($locale); + foreach ($locoCatalogue->all($domain) as $key => $message) { + $catalogue->set($this->retrieveKeyFromId($key, $domain), $message, $domain); + } - foreach ($locoCatalogue->all($domain) as $key => $message) { - $catalogue->set($this->retrieveKeyFromId($key, $domain), $message, $domain); + $translatorBag->addCatalogue($catalogue); } - - $translatorBag->addCatalogue($catalogue); } return $translatorBag; From d95f49e202af8f0a911bf14e9808053065a918f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20TAMARELLE?= Date: Fri, 3 Dec 2021 17:14:10 +0100 Subject: [PATCH 26/41] Remove dead code in tests --- .../Tests/Command/EventDispatcherDebugCommandTest.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php index ce653c6bfaaaa..a506ac2d2915f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/EventDispatcherDebugCommandTest.php @@ -41,12 +41,6 @@ public function provideCompletionSuggestions() private function createCommandCompletionTester(): CommandCompletionTester { - $dispatcher = new EventDispatcher(); - $otherDispatcher = new EventDispatcher(); - - $dispatcher->addListener('event', ['Listener']); - $otherDispatcher->addListener('other_event', ['OtherListener']); - $dispatchers = new ServiceLocator([ 'event_dispatcher' => function () { $dispatcher = new EventDispatcher(); From 05e78b34c569965f709fd4ba44e5bc02ec253334 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 4 Dec 2021 18:10:39 +0100 Subject: [PATCH 27/41] [SecurityBundle] Fix ambiguous deprecation message on missing provider --- .../SecurityBundle/DependencyInjection/SecurityExtension.php | 2 +- .../Tests/DependencyInjection/SecurityExtensionTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index d937a54c43dfc..d64b2c38ac7e7 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -704,7 +704,7 @@ private function getUserProvider(ContainerBuilder $container, string $id, array if ('remember_me' === $factoryKey || 'anonymous' === $factoryKey || 'custom_authenticators' === $factoryKey) { if ('custom_authenticators' === $factoryKey) { - trigger_deprecation('symfony/security-bundle', '5.4', 'Not configuring explicitly the provider for the "%s" listener on "%s" firewall is deprecated because it\'s ambiguous as there is more than one registered provider.', $factoryKey, $id); + trigger_deprecation('symfony/security-bundle', '5.4', 'Not configuring explicitly the provider for the "%s" firewall is deprecated because it\'s ambiguous as there is more than one registered provider. Set the "provider" key to one of the configured providers, even if your custom authenticators don\'t use it.', $id); } return 'security.user_providers'; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 5037bf2b93549..4f8c8ce127a16 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -397,7 +397,7 @@ public function testFirewallWithNoUserProviderTriggerDeprecation() ], ]); - $this->expectDeprecation('Since symfony/security-bundle 5.4: Not configuring explicitly the provider for the "custom_authenticators" listener on "some_firewall" firewall is deprecated because it\'s ambiguous as there is more than one registered provider.'); + $this->expectDeprecation('Since symfony/security-bundle 5.4: Not configuring explicitly the provider for the "some_firewall" firewall is deprecated because it\'s ambiguous as there is more than one registered provider. Set the "provider" key to one of the configured providers, even if your custom authenticators don\'t use it.'); $container->compile(); } From 3842b3ada76c56bdbf91393ceccf56491b2773e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=B6ller?= Date: Sun, 5 Dec 2021 16:02:40 +0100 Subject: [PATCH 28/41] Fix: Wording --- .../Bundle/FrameworkBundle/Command/ContainerLintCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php index 137311bd6358d..2df5b72559c64 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php @@ -74,7 +74,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $io->success('The container was lint successfully: all services are injected with values that are compatible with their type declarations.'); + $io->success('The container was linted successfully: all services are injected with values that are compatible with their type declarations.'); return 0; } From c1c8c2067723be3876e08d5c14b26a539d4d4e54 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 5 Dec 2021 16:41:54 +0100 Subject: [PATCH 29/41] Fix parameter types for ProcessHelper::mustRun() --- src/Symfony/Component/Console/Helper/ProcessHelper.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/ProcessHelper.php b/src/Symfony/Component/Console/Helper/ProcessHelper.php index d580357b93ffd..862d09f214522 100644 --- a/src/Symfony/Component/Console/Helper/ProcessHelper.php +++ b/src/Symfony/Component/Console/Helper/ProcessHelper.php @@ -95,10 +95,10 @@ public function run(OutputInterface $output, $cmd, $error = null, callable $call * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * - * @param string|Process $cmd An instance of Process or a command to run - * @param string|null $error An error message that must be displayed if something went wrong - * @param callable|null $callback A PHP callback to run whenever there is some - * output available on STDOUT or STDERR + * @param array|Process $cmd An instance of Process or a command to run + * @param string|null $error An error message that must be displayed if something went wrong + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR * * @return Process The process that ran * From 62581a9c9961119238c06ad3d4c286f6201bf11b Mon Sep 17 00:00:00 2001 From: Tomasz Kusy Date: Sun, 5 Dec 2021 19:21:16 +0100 Subject: [PATCH 30/41] Fix TranslationTrait for multiple domains --- .../Translation/Command/TranslationTrait.php | 3 +- .../Command/TranslationPullCommandTest.php | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Translation/Command/TranslationTrait.php b/src/Symfony/Component/Translation/Command/TranslationTrait.php index 6a2b1ba86ded3..eafaffd3f10d4 100644 --- a/src/Symfony/Component/Translation/Command/TranslationTrait.php +++ b/src/Symfony/Component/Translation/Command/TranslationTrait.php @@ -32,8 +32,7 @@ private function readLocalTranslations(array $locales, array $domains, array $tr if ($domains) { foreach ($domains as $domain) { - $catalogue = $this->filterCatalogue($catalogue, $domain); - $bag->addCatalogue($catalogue); + $bag->addCatalogue($this->filterCatalogue($catalogue, $domain)); } } else { $bag->addCatalogue($catalogue); diff --git a/src/Symfony/Component/Translation/Tests/Command/TranslationPullCommandTest.php b/src/Symfony/Component/Translation/Tests/Command/TranslationPullCommandTest.php index 2d647341bfbf1..7494a1c84c8fc 100644 --- a/src/Symfony/Component/Translation/Tests/Command/TranslationPullCommandTest.php +++ b/src/Symfony/Component/Translation/Tests/Command/TranslationPullCommandTest.php @@ -424,6 +424,83 @@ public function testPullMessagesWithDefaultLocale() , file_get_contents($filenameFr)); } + public function testPullMessagesMultipleDomains() + { + $arrayLoader = new ArrayLoader(); + $filenameMessages = $this->createFile(['note' => 'NOTE']); + $filenameDomain = $this->createFile(['note' => 'NOTE'], 'en', 'domain.%locale%.xlf'); + $locales = ['en']; + $domains = ['messages', 'domain']; + + $providerReadTranslatorBag = new TranslatorBag(); + $providerReadTranslatorBag->addCatalogue($arrayLoader->load([ + 'new.foo' => 'newFoo', + ], 'en')); + + $providerReadTranslatorBag->addCatalogue($arrayLoader->load([ + 'new.foo' => 'newFoo', + ], 'en', + 'domain' + )); + + $provider = $this->createMock(ProviderInterface::class); + $provider->expects($this->once()) + ->method('read') + ->with($domains, $locales) + ->willReturn($providerReadTranslatorBag); + + $provider->expects($this->once()) + ->method('__toString') + ->willReturn('null://default'); + + $tester = $this->createCommandTester($provider, $locales, $domains, 'en'); + $tester->execute(['--locales' => ['en'], '--domains' => ['messages', 'domain']]); + + $this->assertStringContainsString('[OK] New translations from "null" has been written locally (for "en" locale(s), and "messages, domain" domain(s)).', trim($tester->getDisplay())); + $this->assertXmlStringEqualsXmlString(<< + + +
+ +
+ + + new.foo + newFoo + + + note + NOTE + + +
+
+XLIFF + , file_get_contents($filenameMessages)); + $this->assertXmlStringEqualsXmlString(<< + + +
+ +
+ + + new.foo + newFoo + + + note + NOTE + + +
+
+XLIFF + , file_get_contents($filenameDomain)); + } + private function createCommandTester(ProviderInterface $provider, array $locales = ['en'], array $domains = ['messages'], $defaultLocale = 'en'): CommandTester { $writer = new TranslationWriter(); From 36b466e0f2a7c4045e66ee27691721ea188afe76 Mon Sep 17 00:00:00 2001 From: "simon.chrzanowski" Date: Fri, 3 Dec 2021 11:20:33 +0100 Subject: [PATCH 31/41] use $sessionId instead of $sessionCookiePath on SessionUtils::popSessionCookie call --- .../HttpKernel/EventListener/AbstractSessionListener.php | 2 +- .../HttpKernel/Tests/EventListener/SessionListenerTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php index 0867cad073dea..08b6faac0e7e9 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/AbstractSessionListener.php @@ -146,7 +146,7 @@ public function onKernelResponse(ResponseEvent $event) $sessionCookieHttpOnly = $this->sessionOptions['cookie_httponly'] ?? true; $sessionCookieSameSite = $this->sessionOptions['cookie_samesite'] ?? Cookie::SAMESITE_LAX; - SessionUtils::popSessionCookie($sessionName, $sessionCookiePath); + SessionUtils::popSessionCookie($sessionName, $sessionId); $request = $event->getRequest(); $requestSessionCookieId = $request->cookies->get($sessionName); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php index d82aba64513e4..9924c27d11af9 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php @@ -312,6 +312,7 @@ public function testSessionUsageLogIfStatelessAndSessionUsed() public function testSessionIsSavedWhenUnexpectedSessionExceptionThrown() { $session = $this->createMock(Session::class); + $session->expects($this->exactly(1))->method('getId')->willReturn('123456'); $session->expects($this->exactly(1))->method('getName')->willReturn('PHPSESSID'); $session->method('isStarted')->willReturn(true); $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); From f3c196a03f0b2d9dadae0cf9f987f37512593ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20TAMARELLE?= Date: Mon, 6 Dec 2021 17:23:18 +0100 Subject: [PATCH 32/41] Handle alias in completion script --- src/Symfony/Component/Console/Resources/completion.bash | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Component/Console/Resources/completion.bash b/src/Symfony/Component/Console/Resources/completion.bash index 971af088ba116..c5e89c3c282ab 100644 --- a/src/Symfony/Component/Console/Resources/completion.bash +++ b/src/Symfony/Component/Console/Resources/completion.bash @@ -9,6 +9,12 @@ _sf_{{ COMMAND_NAME }}() { # Use newline as only separator to allow space in completion values IFS=$'\n' local sf_cmd="${COMP_WORDS[0]}" + + # for an alias, get the real script behind it + if [[ $(type -t $sf_cmd) == "alias" ]]; then + sf_cmd=$(alias $sf_cmd | sed -E "s/alias $sf_cmd='(.*)'/\1/") + fi + if [ ! -f "$sf_cmd" ]; then return 1 fi From 681b4c1853257d603bb2792a089cfc269dfe16de Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Mon, 6 Dec 2021 20:27:27 +0100 Subject: [PATCH 33/41] Fix KernelBrowser::loginUser() causing deprecation --- src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php index c5bad9c4e5185..d77708036b4d8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php +++ b/src/Symfony/Bundle/FrameworkBundle/KernelBrowser.php @@ -125,7 +125,7 @@ public function loginUser(object $user, string $firewallContext = 'main'): self $token = new TestBrowserToken($user->getRoles(), $user, $firewallContext); // @deprecated since Symfony 5.4 if (method_exists($token, 'setAuthenticated')) { - $token->setAuthenticated(true); + $token->setAuthenticated(true, false); } $container = $this->getContainer(); From 63534799518c9b860003dda14d9b25f8b0dfcfad Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Tue, 7 Dec 2021 12:11:51 +0100 Subject: [PATCH 34/41] Remove duplicated entry in UPGRADE-6.0.md --- UPGRADE-6.0.md | 1 - 1 file changed, 1 deletion(-) diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 0f3b9e29bbd77..18c46c0b55aa8 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -124,7 +124,6 @@ HttpFoundation * Removed the `Request::HEADER_X_FORWARDED_ALL` constant, use either `Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO` or `Request::HEADER_X_FORWARDED_AWS_ELB` or `Request::HEADER_X_FORWARDED_TRAEFIK`constants instead * Rename `RequestStack::getMasterRequest()` to `getMainRequest()` * Not passing `FILTER_REQUIRE_ARRAY` or `FILTER_FORCE_ARRAY` flags to `InputBag::filter()` when filtering an array will throw `BadRequestException` - * Removed the `Request::HEADER_X_FORWARDED_ALL` constant * Retrieving non-scalar values using `InputBag::get()` will throw `BadRequestException` (use `InputBad::all()` instead to retrieve an array) * Passing non-scalar default value as the second argument `InputBag::get()` will throw `\InvalidArgumentException` * Passing non-scalar, non-array value as the second argument `InputBag::set()` will throw `\InvalidArgumentException` From 94265270b1e048e827b4b6e753961875b6803cbc Mon Sep 17 00:00:00 2001 From: Gary PEGEOT Date: Tue, 7 Dec 2021 12:41:14 +0000 Subject: [PATCH 35/41] [Messenger] [DI] Add auto-registration for BatchHandlerInterface --- .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 17950515dd922..3c46bc4609981 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -107,6 +107,7 @@ use Symfony\Component\Messenger\Bridge\Amqp\Transport\AmqpTransportFactory; use Symfony\Component\Messenger\Bridge\Beanstalkd\Transport\BeanstalkdTransportFactory; use Symfony\Component\Messenger\Bridge\Redis\Transport\RedisTransportFactory; +use Symfony\Component\Messenger\Handler\BatchHandlerInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; use Symfony\Component\Messenger\MessageBus; use Symfony\Component\Messenger\MessageBusInterface; @@ -582,6 +583,8 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('validator.initializer'); $container->registerForAutoconfiguration(MessageHandlerInterface::class) ->addTag('messenger.message_handler'); + $container->registerForAutoconfiguration(BatchHandlerInterface::class) + ->addTag('messenger.message_handler'); $container->registerForAutoconfiguration(TransportFactoryInterface::class) ->addTag('messenger.transport_factory'); $container->registerForAutoconfiguration(MimeTypeGuesserInterface::class) From dfb9de48d99cc6d2286c7abb767f4a72a078f762 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Tue, 7 Dec 2021 17:35:17 +0100 Subject: [PATCH 36/41] Fix UPGRADE files for framework.messenger.reset_on_message option --- UPGRADE-5.4.md | 4 ++-- UPGRADE-6.0.md | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/UPGRADE-5.4.md b/UPGRADE-5.4.md index 2f5ca06682a12..d7492d23f3cfb 100644 --- a/UPGRADE-5.4.md +++ b/UPGRADE-5.4.md @@ -38,6 +38,7 @@ FrameworkBundle * Deprecate `get()`, `has()`, `getDoctrine()`, and `dispatchMessage()` in `AbstractController`, use method/constructor injection instead * Deprecate the `cache.adapter.doctrine` service: The Doctrine Cache library is deprecated. Either switch to Symfony Cache or use the PSR-6 adapters provided by Doctrine Cache. * In `framework.cache` configuration, using `cache.adapter.pdo` adapter with a Doctrine DBAL connection is deprecated, use `cache.adapter.doctrine_dbal` instead. + * Deprecate not setting the `framework.messenger.reset_on_message` config option, its default value will change to `true` in 6.0 HttpKernel ---------- @@ -62,13 +63,12 @@ Messenger * Deprecate not setting the `delete_after_ack` config option (or DSN parameter) using the Redis transport, its default value will change to `true` in 6.0 - * Deprecate not setting the `reset_on_message` config option, its default value will change to `true` in 6.0 Monolog ------- * Deprecate `ResetLoggersWorkerSubscriber` to reset buffered logs in messenger - workers, use "reset_on_message" option in messenger configuration instead. + workers, use `framework.messenger.reset_on_message` option in FrameworkBundle messenger configuration instead. SecurityBundle -------------- diff --git a/UPGRADE-6.0.md b/UPGRADE-6.0.md index 18c46c0b55aa8..347263738c7b4 100644 --- a/UPGRADE-6.0.md +++ b/UPGRADE-6.0.md @@ -172,7 +172,6 @@ Messenger * Removed the `prefetch_count` parameter in the AMQP bridge. * Removed the use of TLS option for Redis Bridge, use `rediss://127.0.0.1` instead of `redis://127.0.0.1?tls=1` * The `delete_after_ack` config option of the Redis transport now defaults to `true` - * The `reset_on_message` config option now defaults to `true` Mime ---- From 47298dcef80beefbfa1f8fedcb49fb2ca6fef42f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 8 Dec 2021 11:40:53 +0100 Subject: [PATCH 37/41] do not call preg_match() on null --- src/Symfony/Component/HttpFoundation/Request.php | 2 +- .../Component/HttpFoundation/Tests/RequestTest.php | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index b6e6c3036b80f..cbe61a152a885 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1502,7 +1502,7 @@ public function isMethodCacheable() public function getProtocolVersion() { if ($this->isFromTrustedProxy()) { - preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via'), $matches); + preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via') ?? '', $matches); if ($matches) { return 'HTTP/'.$matches[2]; diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 798c355d37138..6035dd5d32da9 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -2230,7 +2230,10 @@ public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expec $request = new Request(); $request->server->set('SERVER_PROTOCOL', $serverProtocol); $request->server->set('REMOTE_ADDR', '1.1.1.1'); - $request->headers->set('Via', $via); + + if (null !== $via) { + $request->headers->set('Via', $via); + } $this->assertSame($expected, $request->getProtocolVersion()); } @@ -2238,9 +2241,11 @@ public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expec public function protocolVersionProvider() { return [ - 'untrusted without via' => ['HTTP/2.0', false, '', 'HTTP/2.0'], + 'untrusted with empty via' => ['HTTP/2.0', false, '', 'HTTP/2.0'], + 'untrusted without via' => ['HTTP/2.0', false, null, 'HTTP/2.0'], 'untrusted with via' => ['HTTP/2.0', false, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/2.0'], - 'trusted without via' => ['HTTP/2.0', true, '', 'HTTP/2.0'], + 'trusted with empty via' => ['HTTP/2.0', true, '', 'HTTP/2.0'], + 'trusted without via' => ['HTTP/2.0', true, null, 'HTTP/2.0'], 'trusted with via' => ['HTTP/2.0', true, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'], 'trusted with via and protocol name' => ['HTTP/2.0', true, 'HTTP/1.0 fred, HTTP/1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'], 'trusted with broken via' => ['HTTP/2.0', true, 'HTTP/1^0 foo', 'HTTP/2.0'], From fb3f4e403c91d985267f1e0aa8e9d5d17220619e Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 8 Dec 2021 18:38:27 +0100 Subject: [PATCH 38/41] [CI] Fix package-tests workflow checks for contracts --- .github/get-modified-packages.php | 30 ++++++++++++++++++++++++++--- .github/workflows/package-tests.yml | 11 ++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/.github/get-modified-packages.php b/.github/get-modified-packages.php index 9135a1da666e5..a3682af0b9d1a 100644 --- a/.github/get-modified-packages.php +++ b/.github/get-modified-packages.php @@ -17,9 +17,33 @@ return strlen($b) <=> strlen($a) ?: $a <=> $b; }); -function isComponentBridge(string $packageDir): bool +function getPackageType(string $packageDir): string { - return 0 < preg_match('@Symfony/Component/.*/Bridge/@', $packageDir); + if (preg_match('@Symfony/Bridge/@', $packageDir)) { + return 'bridge'; + } + + if (preg_match('@Symfony/Bundle/@', $packageDir)) { + return 'bundle'; + } + + if (preg_match('@Symfony/Component/[^/]+/Bridge/@', $packageDir)) { + return 'component_bridge'; + } + + if (preg_match('@Symfony/Component/@', $packageDir)) { + return 'component'; + } + + if (preg_match('@Symfony/Contracts/@', $packageDir)) { + return 'contract'; + } + + if (preg_match('@Symfony/Contracts$@', $packageDir)) { + return 'contracts'; + } + + throw new \LogicException(); } $newPackage = []; @@ -43,7 +67,7 @@ function isComponentBridge(string $packageDir): bool $output = []; foreach ($modifiedPackages as $directory => $bool) { $name = json_decode(file_get_contents($directory.'/composer.json'), true)['name'] ?? 'unknown'; - $output[] = ['name' => $name, 'directory' => $directory, 'new' => $newPackage[$directory] ?? false, 'component_bridge' => isComponentBridge($directory)]; + $output[] = ['name' => $name, 'directory' => $directory, 'new' => $newPackage[$directory] ?? false, 'type' => getPackageType($directory)]; } echo json_encode($output); diff --git a/.github/workflows/package-tests.yml b/.github/workflows/package-tests.yml index cb66e2d8d3b03..3c0a7c36be89f 100644 --- a/.github/workflows/package-tests.yml +++ b/.github/workflows/package-tests.yml @@ -63,13 +63,18 @@ jobs: DIR=$(_jq '.directory') NAME=$(_jq '.name') echo "::group::$NAME" + TYPE=$(_jq '.type') localExit=0 - _file_exist $DIR/.gitattributes || localExit=1 + if [ $TYPE != 'contract' ] && [ $TYPE != 'contracts' ]; then + _file_exist $DIR/.gitattributes || localExit=1 + fi _file_exist $DIR/.gitignore || localExit=1 _file_exist $DIR/CHANGELOG.md || localExit=1 _file_exist $DIR/LICENSE || localExit=1 - _file_exist $DIR/phpunit.xml.dist || localExit=1 + if [ $TYPE != 'contract' ]; then + _file_exist $DIR/phpunit.xml.dist || localExit=1 + fi _file_exist $DIR/README.md || localExit=1 _file_not_exist $DIR/phpunit.xml || localExit=1 @@ -77,7 +82,7 @@ jobs: echo "Verifying new package" _correct_license_file $DIR/LICENSE || localExit=1 - if [ $(_jq '.component_bridge') == false ]; then + if [ $TYPE == 'component_bridge' ]; then if [ ! $(cat composer.json | jq -e ".replace.\"$NAME\"|test(\"self.version\")") ]; then echo "Composer.json's replace section needs to contain $NAME" localExit=1 From ef050c2db690cfea38b85529d7333989e30ace8c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 9 Dec 2021 12:22:43 +0100 Subject: [PATCH 39/41] Fix polyfill-php73 requirement --- src/Symfony/Component/Console/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 2a7b429ac1f8b..9a565068cdedd 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -19,7 +19,7 @@ "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.1|^2|^3", "symfony/string": "^5.1|^6.0" From 8cd331a6fa8e089cac70f8b4338fa857add6a7ef Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 9 Dec 2021 14:35:48 +0100 Subject: [PATCH 40/41] Update CHANGELOG for 5.4.1 --- CHANGELOG-5.4.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG-5.4.md b/CHANGELOG-5.4.md index 5ba6dab3b6129..5cc4204a52f35 100644 --- a/CHANGELOG-5.4.md +++ b/CHANGELOG-5.4.md @@ -7,6 +7,30 @@ in 5.4 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v5.4.0...v5.4.1 +* 5.4.1 (2021-12-09) + + * bug #44490 [DependencyInjection][Messenger] Add auto-registration for BatchHandlerInterface (GaryPEGEOT) + * bug #44523 [Console] Fix polyfill-php73 requirement (Seldaek) + * bug #44502 [HttpFoundation] do not call preg_match() on null (xabbuh) + * bug #44475 [Console] Handle alias in completion script (GromNaN) + * bug #44481 [FrameworkBundle] Fix loginUser() causing deprecation (wouterj) + * bug #44416 [Translation] Make http requests synchronous when reading the Loco API (Kocal) + * bug #44437 [HttpKernel] Fix wrong usage of SessionUtils::popSessionCookie (simonchrz) + * bug #44350 [Translation] Fix TranslationTrait (Tomasz Kusy) + * bug #44460 [SecurityBundle] Fix ambiguous deprecation message on missing provider (chalasr) + * bug #44467 [Console] Fix parameter types for `ProcessHelper::mustRun()` (derrabus) + * bug #44427 [FrameworkBundle] Fix compatibility with symfony/security-core 6.x (deps=high tests) (wouterj) + * bug #44424 [SecurityBundle] Don't rely on deprecated strategy constants (derrabus) + * bug #44399 Prevent infinite nesting of lazy `ObjectManager` instances when `ObjectManager` is reset (Ocramius) + * bug #44395 [HttpKernel] fix sending Vary: Accept-Language when appropriate (nicolas-grekas) + * bug #44385 [DependencyInjection] Skip parameter attribute configurators in AttributeAutoconfigurationPass if we can't get the constructor reflector (fancyweb) + * bug #44359 Avoid duplicated session listener registration in tests (alexander-schranz) + * bug #44375 [DoctrineBridge] fix calling get_class on non-object (kbond) + * bug #44378 [HttpFoundation] fix SessionHandlerFactory using connections (dmaicher) + * bug #44365 [SecurityBundle]  Fix invalid reference with `always_authenticate_before_granting` (chalasr) + * bug #44361 [HttpClient] Fix handling error info in MockResponse (fancyweb) + * bug #44370 [Lock] create lock table if it does not exist (martinssipenko) + * 5.4.0 (2021-11-29) * bug #44309 [Messenger] Leverage DBAL's getNativeConnection() method (derrabus) From 9daa5871a493dde4831f3b87b1aa2c61b787d684 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 9 Dec 2021 14:36:09 +0100 Subject: [PATCH 41/41] Update VERSION for 5.4.1 --- 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 6a5546de95007..35353377029cc 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,12 +78,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.1-DEV'; + public const VERSION = '5.4.1'; public const VERSION_ID = 50401; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; public const RELEASE_VERSION = 1; - public const EXTRA_VERSION = 'DEV'; + public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2024'; public const END_OF_LIFE = '11/2025';