From 3e258504f6e66b5ede1c105f59ef93ca9dcaeb26 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 09:44:43 +0100 Subject: [PATCH 01/42] updated CHANGELOG for 3.4.35 --- CHANGELOG-3.4.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index a72767317ec96..ba1027925d004 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG-3.4.md @@ -7,6 +7,13 @@ in 3.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/v3.4.0...v3.4.1 +* 3.4.35 (2019-11-13) + + * bug #34344 [Console] Constant STDOUT might be undefined (nicolas-grekas) + * security #cve-2019-18889 [Cache] forbid serializing AbstractAdapter and TagAwareAdapter instances (nicolas-grekas) + * security #cve-2019-18888 [HttpFoundation] fix guessing mime-types of files with leading dash (nicolas-grekas) + * security #cve-2019-18887 [HttpKernel] Use constant time comparison in UriSigner (stof) + * 3.4.34 (2019-11-11) * bug #34297 [DI] fix locators with numeric keys (nicolas-grekas) From 02257c80981f1a30a8a5b13652161f97ad7b7c08 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 09:44:50 +0100 Subject: [PATCH 02/42] updated VERSION for 3.4.35 --- 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 2543f59245851..05b11f3665c5c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -67,12 +67,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.35-DEV'; + const VERSION = '3.4.35'; const VERSION_ID = 30435; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; const RELEASE_VERSION = 35; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From 8a68d2d358ae7db406f72711c24d5c8f687cf7b6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 09:48:47 +0100 Subject: [PATCH 03/42] bumped Symfony version to 3.4.36 --- 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 05b11f3665c5c..25236948695dc 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -67,12 +67,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.35'; - const VERSION_ID = 30435; + const VERSION = '3.4.36-DEV'; + const VERSION_ID = 30436; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 35; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 36; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From 443a83bed484b9be084c0a91c82e1664b7781010 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 10:06:52 +0100 Subject: [PATCH 04/42] updated CHANGELOG for 4.3.8 --- CHANGELOG-4.3.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG-4.3.md b/CHANGELOG-4.3.md index df5f4ef4396b6..a5b9b78847b5c 100644 --- a/CHANGELOG-4.3.md +++ b/CHANGELOG-4.3.md @@ -7,6 +7,16 @@ in 4.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.3.0...v4.3.1 +* 4.3.8 (2019-11-13) + + * bug #34344 [Console] Constant STDOUT might be undefined (nicolas-grekas) + * security #cve-2019-18886 [Security\Core] throw AccessDeniedException when switch user fails (nicolas-grekas) + * security #cve-2019-18888 [Mime] fix guessing mime-types of files with leading dash (nicolas-grekas) + * security #cve-2019-11325 [VarExporter] fix exporting some strings (nicolas-grekas) + * security #cve-2019-18889 [Cache] forbid serializing AbstractAdapter and TagAwareAdapter instances (nicolas-grekas) + * security #cve-2019-18888 [HttpFoundation] fix guessing mime-types of files with leading dash (nicolas-grekas) + * security #cve-2019-18887 [HttpKernel] Use constant time comparison in UriSigner (stof) + * 4.3.7 (2019-11-11) * bug #34294 [Workflow] Fix error when we use ValueObject for the marking property (FabienSalles) From 3a50fa397d274dba7831388348e83ed4a6cca03f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 10:07:28 +0100 Subject: [PATCH 05/42] updated VERSION for 4.3.8 --- 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 426259388e169..eca2ab61f1358 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -73,12 +73,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '4.3.8-DEV'; + const VERSION = '4.3.8'; const VERSION_ID = 40308; const MAJOR_VERSION = 4; const MINOR_VERSION = 3; const RELEASE_VERSION = 8; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2020'; const END_OF_LIFE = '07/2020'; From d863fc2b4b33e96ed281376f4e6ffaac01ec0f2f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 10:11:31 +0100 Subject: [PATCH 06/42] bumped Symfony version to 4.3.9 --- 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 eca2ab61f1358..ac9775f5f7c64 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -73,12 +73,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '4.3.8'; - const VERSION_ID = 40308; + const VERSION = '4.3.9-DEV'; + const VERSION_ID = 40309; const MAJOR_VERSION = 4; const MINOR_VERSION = 3; - const RELEASE_VERSION = 8; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 9; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2020'; const END_OF_LIFE = '07/2020'; From e8325ed818818bf9ce47ee903fe234111afbd444 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 10:13:29 +0100 Subject: [PATCH 07/42] updated CHANGELOG for 4.4.0-BETA2 --- CHANGELOG-4.4.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG-4.4.md b/CHANGELOG-4.4.md index 3d198692f7360..facb38ff1c67b 100644 --- a/CHANGELOG-4.4.md +++ b/CHANGELOG-4.4.md @@ -7,6 +7,16 @@ in 4.4 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.4.0...v4.4.1 +* 4.4.0-BETA2 (2019-11-13) + + * bug #34344 [Console] Constant STDOUT might be undefined (nicolas-grekas) + * security #cve-2019-18886 [Security\Core] throw AccessDeniedException when switch user fails (nicolas-grekas) + * security #cve-2019-18888 [Mime] fix guessing mime-types of files with leading dash (nicolas-grekas) + * security #cve-2019-11325 [VarExporter] fix exporting some strings (nicolas-grekas) + * security #cve-2019-18889 [Cache] forbid serializing AbstractAdapter and TagAwareAdapter instances (nicolas-grekas) + * security #cve-2019-18888 [HttpFoundation] fix guessing mime-types of files with leading dash (nicolas-grekas) + * security #cve-2019-18887 [HttpKernel] Use constant time comparison in UriSigner (stof) + * 4.4.0-BETA1 (2019-11-12) * feature #34333 Revert "feature #34329 [ExpressionLanguage] add XOR operator (ottaviano)" (nicolas-grekas) From 8c47650d531f92f61a6751e01f9bb06c5f1ee18b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 10:13:36 +0100 Subject: [PATCH 08/42] updated VERSION for 4.4.0-BETA2 --- 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 952d3a0b4f7c4..2b43c038a4d53 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -74,12 +74,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '4.4.0-DEV'; + const VERSION = '4.4.0-BETA2'; const VERSION_ID = 40400; const MAJOR_VERSION = 4; const MINOR_VERSION = 4; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = 'BETA2'; const END_OF_MAINTENANCE = '11/2022'; const END_OF_LIFE = '11/2023'; From 29a2f17124b39b1f0ca258fa7352b80efbd2930e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 10:18:19 +0100 Subject: [PATCH 09/42] bumped Symfony version to 4.4.0 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 2b43c038a4d53..952d3a0b4f7c4 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -74,12 +74,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '4.4.0-BETA2'; + const VERSION = '4.4.0-DEV'; const VERSION_ID = 40400; const MAJOR_VERSION = 4; const MINOR_VERSION = 4; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'BETA2'; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2022'; const END_OF_LIFE = '11/2023'; From c3455b46ebbabaae0242e8b2c3313bb05b830b61 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 13 Nov 2019 10:24:14 +0100 Subject: [PATCH 10/42] bumped Symfony version to 5.0.0 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 61a1fc5c0ce3f..3cd6ad0b829a7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -66,12 +66,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '5.0.0-BETA2'; + const VERSION = '5.0.0-DEV'; const VERSION_ID = 50000; const MAJOR_VERSION = 5; const MINOR_VERSION = 0; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'BETA2'; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2020'; const END_OF_LIFE = '07/2020'; From 4755e160be42b25bcd987410c16c581eaf6258ca Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 13 Nov 2019 22:03:39 +0100 Subject: [PATCH 11/42] [Form] Allow symfony/service-contracts v2. --- src/Symfony/Component/Form/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index b6309a0012e6e..a3dbf875006ca 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -23,7 +23,7 @@ "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", "symfony/property-access": "^3.4|^4.0|^5.0", - "symfony/service-contracts": "~1.1" + "symfony/service-contracts": "^1.1|^2" }, "require-dev": { "doctrine/collections": "~1.0", From 3d2b589af9b89ff1cd7c4d2896f98eb2a0619f88 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 13 Nov 2019 22:26:07 +0100 Subject: [PATCH 12/42] [FrameworkBundle] Disallow WebProfilerBundle < 4.4. --- src/Symfony/Bundle/FrameworkBundle/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index cb778933005df..7022e25a21b88 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -85,6 +85,7 @@ "symfony/twig-bridge": "<4.1.1", "symfony/twig-bundle": "<4.4", "symfony/validator": "<4.4", + "symfony/web-profiler-bundle": "<4.4", "symfony/workflow": "<4.3.6" }, "suggest": { From eccb937d975d90b92e52e9ae689a7d1344d99400 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 13 Nov 2019 22:44:24 +0100 Subject: [PATCH 13/42] [DI] fix detecting singly implemented interfaces --- .../DependencyInjection/Loader/FileLoader.php | 2 +- .../Tests/Loader/FileLoaderTest.php | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index 3d0a076674941..a474613ef7bb0 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -112,7 +112,7 @@ public function registerClasses(Definition $prototype, $namespace, $resource, $e continue; } foreach (class_implements($class, false) as $interface) { - $this->singlyImplemented[$interface] = isset($this->singlyImplemented[$interface]) ? false : $class; + $this->singlyImplemented[$interface] = ($this->singlyImplemented[$interface] ?? $class) !== $class ? false : $class; } } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php index b9ea798d2c5cd..970cf416b3442 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php @@ -91,6 +91,8 @@ public function testRegisterClasses() $loader = new TestFileLoader($container, new FileLocator(self::$fixturesPath.'/Fixtures')); $loader->registerClasses(new Definition(), 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\\', 'Prototype/%sub_dir%/*'); + $loader->registerClasses(new Definition(), 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\\', 'Prototype/%sub_dir%/*'); // loading twice should not be an issue + $loader->registerAliasesForSinglyImplementedInterfaces(); $this->assertEquals( ['service_container', Bar::class], @@ -119,6 +121,7 @@ public function testRegisterClassesWithExclude() // load everything, except OtherDir/AnotherSub & Foo.php 'Prototype/{%other_dir%/AnotherSub,Foo.php}' ); + $loader->registerAliasesForSinglyImplementedInterfaces(); $this->assertTrue($container->has(Bar::class)); $this->assertTrue($container->has(Baz::class)); @@ -148,6 +151,8 @@ public function testRegisterClassesWithExcludeAsArray() 'Prototype/OtherDir/AnotherSub/DeeperBaz.php', ] ); + $loader->registerAliasesForSinglyImplementedInterfaces(); + $this->assertTrue($container->has(Foo::class)); $this->assertTrue($container->has(Baz::class)); $this->assertFalse($container->has(Bar::class)); @@ -162,6 +167,7 @@ public function testNestedRegisterClasses() $prototype = new Definition(); $prototype->setPublic(true)->setPrivate(true); $loader->registerClasses($prototype, 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\', 'Prototype/*'); + $loader->registerAliasesForSinglyImplementedInterfaces(); $this->assertTrue($container->has(Bar::class)); $this->assertTrue($container->has(Baz::class)); @@ -193,6 +199,7 @@ public function testMissingParentClass() 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\BadClasses\\', 'Prototype/%bad_classes_dir%/*' ); + $loader->registerAliasesForSinglyImplementedInterfaces(); $this->assertTrue($container->has(MissingParent::class)); @@ -211,6 +218,7 @@ public function testRegisterClassesWithBadPrefix() // the Sub is missing from namespace prefix $loader->registerClasses(new Definition(), 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\', 'Prototype/Sub/*'); + $loader->registerAliasesForSinglyImplementedInterfaces(); } public function testRegisterClassesWithIncompatibleExclude() @@ -226,6 +234,7 @@ public function testRegisterClassesWithIncompatibleExclude() 'Prototype/*', 'yaml/*' ); + $loader->registerAliasesForSinglyImplementedInterfaces(); } } @@ -240,10 +249,4 @@ public function supports($resource, $type = null): bool { return false; } - - public function registerClasses(Definition $prototype, $namespace, $resource, $exclude = null) - { - parent::registerClasses($prototype, $namespace, $resource, $exclude); - $this->registerAliasesForSinglyImplementedInterfaces(); - } } From abcf63aaa8a5ee84f3a2b35c384ce496673c92ac Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 14 Nov 2019 15:24:33 +0100 Subject: [PATCH 14/42] [Mailer] Add UPGRADE entry about the null transport DSN --- UPGRADE-4.4.md | 5 +++++ src/Symfony/Component/Mailer/CHANGELOG.md | 1 + 2 files changed, 6 insertions(+) diff --git a/UPGRADE-4.4.md b/UPGRADE-4.4.md index aef34c47bd61d..1d1863e4f84a2 100644 --- a/UPGRADE-4.4.md +++ b/UPGRADE-4.4.md @@ -164,6 +164,11 @@ Lock * Deprecated services `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract`, use `StoreFactory::createStore` instead. +Mailer +------ + + * [BC BREAK] Changed the DSN to use for disabling delivery (using the `NullTransport`) from `smtp://null` to `null://null` (host doesn't matter). + Messenger --------- diff --git a/src/Symfony/Component/Mailer/CHANGELOG.md b/src/Symfony/Component/Mailer/CHANGELOG.md index 060d333d74824..051984f00160c 100644 --- a/src/Symfony/Component/Mailer/CHANGELOG.md +++ b/src/Symfony/Component/Mailer/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.4.0 ----- + * [BC BREAK] changed the `NullTransport` DSN from `smtp://null` to `null://null` * [BC BREAK] renamed `SmtpEnvelope` to `Envelope`, renamed `DelayedSmtpEnvelope` to `DelayedEnvelope` * [BC BREAK] changed the syntax for failover and roundrobin DSNs From 78dad79fec4a55893cd04e8255c9a66cf34f5be1 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Thu, 14 Nov 2019 16:04:06 +0100 Subject: [PATCH 15/42] [WebProfilerBundle] Require symfony/twig-bundle --- src/Symfony/Bundle/WebProfilerBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 241a5e350b414..c82ef0fe0093d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -20,7 +20,7 @@ "symfony/http-kernel": "~3.4.25|^4.2.6", "symfony/polyfill-php70": "~1.0", "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0", + "symfony/twig-bundle": "~2.8|~3.0|~4.0", "symfony/var-dumper": "~3.3|~4.0", "twig/twig": "~1.34|~2.4" }, From 600ae332620015e750aed76fc825a4b48f03be52 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 14 Nov 2019 19:27:47 +0100 Subject: [PATCH 16/42] [DI] Use reproducible entropy to generate env placeholders --- .../ParameterBag/EnvPlaceholderParameterBag.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index fe27324e54f11..872408690b926 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -24,6 +24,8 @@ class EnvPlaceholderParameterBag extends ParameterBag private $unusedEnvPlaceholders = []; private $providedTypes = []; + private static $counter = 0; + /** * {@inheritdoc} */ @@ -57,7 +59,7 @@ public function get($name) } } - $uniqueName = md5($name.uniqid(mt_rand(), true)); + $uniqueName = md5($name.'_'.self::$counter++); $placeholder = sprintf('%s_%s_%s', $this->getEnvPlaceholderUniquePrefix(), str_replace(':', '_', $env), $uniqueName); $this->envPlaceholders[$env][$placeholder] = $placeholder; @@ -72,7 +74,13 @@ public function get($name) */ public function getEnvPlaceholderUniquePrefix(): string { - return $this->envPlaceholderUniquePrefix ?? $this->envPlaceholderUniquePrefix = 'env_'.bin2hex(random_bytes(8)); + if (null === $this->envPlaceholderUniquePrefix) { + $reproducibleEntropy = unserialize(serialize($this->parameters)); + array_walk_recursive($reproducibleEntropy, function (&$v) { $v = null; }); + $this->envPlaceholderUniquePrefix = 'env_'.substr(md5(serialize($reproducibleEntropy)), -16); + } + + return $this->envPlaceholderUniquePrefix; } /** From 797450d6b8a67f72f855e655bb6965889884473d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 14 Nov 2019 23:50:50 +0100 Subject: [PATCH 17/42] [Security] always check the token on non-lazy firewalls --- .../Component/Security/Http/Firewall/AccessListener.php | 7 ++++++- .../Security/Http/Tests/Firewall/AccessListenerTest.php | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php index cecb18568b300..6164adde5db02 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AccessListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AccessListener.php @@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Http\AccessMapInterface; +use Symfony\Component\Security\Http\Event\LazyResponseEvent; /** * AccessListener enforces access control rules. @@ -51,6 +52,10 @@ public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionM */ public function __invoke(RequestEvent $event) { + if (!$event instanceof LazyResponseEvent && null === $token = $this->tokenStorage->getToken()) { + throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.'); + } + $request = $event->getRequest(); list($attributes) = $this->map->getPatterns($request); @@ -59,7 +64,7 @@ public function __invoke(RequestEvent $event) return; } - if (null === $token = $this->tokenStorage->getToken()) { + if ($event instanceof LazyResponseEvent && null === $token = $this->tokenStorage->getToken()) { throw new AuthenticationCredentialsNotFoundException('A Token was not found in the TokenStorage.'); } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php index 08515164971c3..1dff48dfda84f 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php @@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Http\AccessMapInterface; +use Symfony\Component\Security\Http\Event\LazyResponseEvent; use Symfony\Component\Security\Http\Firewall\AccessListener; class AccessListenerTest extends TestCase @@ -219,7 +220,7 @@ public function testHandleWhenAccessMapReturnsEmptyAttributes() ->willReturn($request) ; - $listener($event); + $listener(new LazyResponseEvent($event)); } public function testHandleWhenTheSecurityTokenStorageHasNoToken() From 2c2632a04cd0913aadcabb7a3070f681b13496f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 14 Nov 2019 23:35:53 +0100 Subject: [PATCH 18/42] [SecurityBundle] add tests with empty authenticator --- .../Tests/Functional/AnonymousTest.php | 24 ++++++++ .../AppCustomAuthenticator.php | 57 +++++++++++++++++++ .../Functional/app/Anonymous/bundles.php | 15 +++++ .../Tests/Functional/app/Anonymous/config.yml | 24 ++++++++ .../Functional/app/Anonymous/routing.yml | 5 ++ 5 files changed, 125 insertions(+) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/AnonymousTest.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AnonymousBundle/AppCustomAuthenticator.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/bundles.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/config.yml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/routing.yml diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AnonymousTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AnonymousTest.php new file mode 100644 index 0000000000000..fdee9bce9b06a --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AnonymousTest.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Functional; + +class AnonymousTest extends AbstractWebTestCase +{ + public function testAnonymous() + { + $client = $this->createClient(['test_case' => 'Anonymous', 'root_config' => 'config.yml']); + + $client->request('GET', '/'); + + $this->assertSame(401, $client->getResponse()->getStatusCode()); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AnonymousBundle/AppCustomAuthenticator.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AnonymousBundle/AppCustomAuthenticator.php new file mode 100644 index 0000000000000..5069fa9cc7fa9 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AnonymousBundle/AppCustomAuthenticator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AnonymousBundle; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; +use Symfony\Component\Security\Guard\AbstractGuardAuthenticator; + +class AppCustomAuthenticator extends AbstractGuardAuthenticator +{ + public function supports(Request $request) + { + return false; + } + + public function getCredentials(Request $request) + { + } + + public function getUser($credentials, UserProviderInterface $userProvider) + { + } + + public function checkCredentials($credentials, UserInterface $user) + { + } + + public function onAuthenticationFailure(Request $request, AuthenticationException $exception) + { + } + + public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) + { + } + + public function start(Request $request, AuthenticationException $authException = null) + { + return new Response($authException->getMessage(), Response::HTTP_UNAUTHORIZED); + } + + public function supportsRememberMe() + { + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/bundles.php new file mode 100644 index 0000000000000..d1e9eb7e0d36a --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/bundles.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), + new Symfony\Bundle\SecurityBundle\SecurityBundle(), +]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/config.yml new file mode 100644 index 0000000000000..8ee417ab3a17d --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/config.yml @@ -0,0 +1,24 @@ +framework: + secret: test + router: { resource: "%kernel.project_dir%/%kernel.test_case%/routing.yml" } + validation: { enabled: true, enable_annotations: true } + csrf_protection: true + form: true + test: ~ + default_locale: en + session: + storage_id: session.storage.mock_file + profiler: { only_exceptions: false } + +services: + Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AnonymousBundle\AppCustomAuthenticator: ~ + +security: + firewalls: + secure: + pattern: ^/ + anonymous: false + stateless: true + guard: + authenticators: + - Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AnonymousBundle\AppCustomAuthenticator diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/routing.yml new file mode 100644 index 0000000000000..4d11154375219 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Anonymous/routing.yml @@ -0,0 +1,5 @@ +main: + path: / + defaults: + _controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction + path: /app From 1752dd9432d53e770187ebb1c4078c1966086dae Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 15 Nov 2019 10:12:35 +0100 Subject: [PATCH 19/42] add FrameworkBundle requirement --- src/Symfony/Bundle/WebProfilerBundle/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 30c4e7a732bf1..11e3f5b68301e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -18,6 +18,7 @@ "require": { "php": "^7.1.3", "symfony/config": "^4.2|^5.0", + "symfony/framework-bundle": "^4.4|^5.0", "symfony/http-kernel": "^4.4", "symfony/routing": "^3.4|^4.0|^5.0", "symfony/twig-bundle": "^4.2|^5.0", From d969d49292df3125d37c468ba0ccc267a49834ad Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Nov 2019 11:02:26 +0100 Subject: [PATCH 20/42] [FrameworkBundle] fix wiring of httplug client --- .../Bundle/FrameworkBundle/Resources/config/http_client.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.xml index 766e9f6d33d31..10256b69d5e96 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/http_client.xml @@ -26,8 +26,8 @@ - - + + From e6c9d77b63ba7449b3b386b54f60ed18e0db3872 Mon Sep 17 00:00:00 2001 From: Damien Alexandre Date: Fri, 15 Nov 2019 15:28:29 +0100 Subject: [PATCH 21/42] [Finder] Allow ssh2 stream wrapper for sftp Same fix as #28604 but for the ss2.sftp wrapper. --- src/Symfony/Component/Finder/Finder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 6624e840791fb..c8f642d872ce3 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -746,7 +746,7 @@ private function normalizeDir($dir) { $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR); - if (preg_match('#^s?ftp://#', $dir)) { + if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) { $dir .= '/'; } From 7f9556ce1931a4021a320ef688247f846b87d2b5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Nov 2019 16:19:43 +0100 Subject: [PATCH 22/42] [HttpKernel] dont check cache freshness more than once per process --- src/Symfony/Component/HttpKernel/Kernel.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 952d3a0b4f7c4..47f0b49b58d8d 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -74,6 +74,8 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; + private static $freshCache = []; + const VERSION = '4.4.0-DEV'; const VERSION_ID = 40400; const MAJOR_VERSION = 4; @@ -511,7 +513,9 @@ protected function initializeContainer() $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); try { - if (file_exists($cachePath) && \is_object($this->container = include $cachePath) && (!$this->debug || $cache->isFresh())) { + if (file_exists($cachePath) && \is_object($this->container = include $cachePath) + && (!$this->debug || (self::$freshCache[$k = $cachePath.'.'.$this->environment] ?? self::$freshCache[$k] = $cache->isFresh())) + ) { $this->container->set('kernel', $this); error_reporting($errorLevel); From 6adbfa2ae7a3153e9d2368ce9b2ce5bbb362fad7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Nov 2019 16:26:16 +0100 Subject: [PATCH 23/42] [Config] fix id-generation for GlobResource --- src/Symfony/Component/Config/Resource/GlobResource.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Resource/GlobResource.php b/src/Symfony/Component/Config/Resource/GlobResource.php index bf332fde32722..6c2539a2de15b 100644 --- a/src/Symfony/Component/Config/Resource/GlobResource.php +++ b/src/Symfony/Component/Config/Resource/GlobResource.php @@ -41,6 +41,7 @@ class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface */ public function __construct(?string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = []) { + ksort($excludedPrefixes); $this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false); $this->pattern = $pattern; $this->recursive = $recursive; @@ -62,7 +63,7 @@ public function getPrefix() */ public function __toString() { - return 'glob.'.$this->prefix.$this->pattern.(int) $this->recursive; + return 'glob.'.$this->prefix.(int) $this->recursive.$this->pattern.(int) $this->forExclusion.implode("\0", $this->excludedPrefixes); } /** From 7824d75ac3854f11e8f4f845c0765abbdeffbe6e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Nov 2019 17:50:43 +0100 Subject: [PATCH 24/42] [HttpKernel] collect bundle classes, not paths --- .../Resources/views/Collector/config.html.twig | 2 +- .../HttpKernel/DataCollector/ConfigDataCollector.php | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig index bfed460ab7c99..c085303213897 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig @@ -210,7 +210,7 @@ Name - Path + Class diff --git a/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php index 3b63f3a99cc83..266d97626f732 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php @@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\VarDumper\Caster\LinkStub; +use Symfony\Component\VarDumper\Caster\ClassStub; /** * @author Fabien Potencier @@ -30,7 +30,6 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte private $kernel; private $name; private $version; - private $hasVarDumper; public function __construct(string $name = null, string $version = null) { @@ -43,7 +42,6 @@ public function __construct(string $name = null, string $version = null) $this->name = $name; $this->version = $version; - $this->hasVarDumper = class_exists(LinkStub::class); } /** @@ -82,7 +80,7 @@ public function collect(Request $request, Response $response/*, \Throwable $exce if (isset($this->kernel)) { foreach ($this->kernel->getBundles() as $name => $bundle) { - $this->data['bundles'][$name] = $this->hasVarDumper ? new LinkStub($bundle->getPath()) : $bundle->getPath(); + $this->data['bundles'][$name] = new ClassStub(\get_class($bundle)); } $this->data['symfony_state'] = $this->determineSymfonyState(); From f51adc53f8e965a273d219c33edd47ecd31d341c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Nov 2019 22:08:13 +0100 Subject: [PATCH 25/42] [HttpClient] fix HttpClientDataCollector --- .../HttpClient/DataCollector/HttpClientDataCollector.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php b/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php index 4fdd4a671fb0f..b3b0959465cfe 100644 --- a/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php +++ b/src/Symfony/Component/HttpClient/DataCollector/HttpClientDataCollector.php @@ -135,6 +135,7 @@ private function collectOnClient(TraceableHttpClient $client): array $debugInfo = array_diff_key($info, $baseInfo); $info = array_diff_key($info, $debugInfo) + ['debug_info' => $debugInfo]; + unset($traces[$i]['info']); // break PHP reference used by TraceableHttpClient $traces[$i]['info'] = $this->cloneVar($info); $traces[$i]['options'] = $this->cloneVar($trace['options']); } From e77f6de1e8601ed531f7271a6313403be4d4a584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20R?= Date: Tue, 29 Oct 2019 20:19:10 +0100 Subject: [PATCH 26/42] [Cache] Redis Tag Aware warn on wrong eviction policy --- .../Cache/Adapter/RedisTagAwareAdapter.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php index d52c08d642c6f..1dbce4b0db7d4 100644 --- a/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/RedisTagAwareAdapter.php @@ -14,6 +14,7 @@ use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\PredisCluster; use Predis\Response\Status; +use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Marshaller\DeflateMarshaller; use Symfony\Component\Cache\Marshaller\MarshallerInterface; @@ -58,6 +59,11 @@ class RedisTagAwareAdapter extends AbstractTagAwareAdapter */ private const DEFAULT_CACHE_TTL = 8640000; + /** + * @var string|null detected eviction policy used on Redis server + */ + private $redisEvictionPolicy; + /** * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface $redisClient The redis client * @param string $namespace The default namespace @@ -87,6 +93,13 @@ public function __construct($redisClient, string $namespace = '', int $defaultLi */ protected function doSave(array $values, ?int $lifetime, array $addTagData = [], array $delTagData = []): array { + $eviction = $this->getRedisEvictionPolicy(); + if ('noeviction' !== $eviction && 0 !== strpos($eviction, 'volatile-')) { + CacheItem::log($this->logger, sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies', $eviction)); + + return false; + } + // serialize values if (!$serialized = $this->marshaller->marshall($values, $failed)) { return $failed; @@ -260,4 +273,20 @@ private function renameKeys($redis, array $ids): array return $newIds; } + + private function getRedisEvictionPolicy(): string + { + if (null !== $this->redisEvictionPolicy) { + return $this->redisEvictionPolicy; + } + + foreach ($this->getHosts() as $host) { + $info = $host->info('Memory'); + $info = isset($info['Memory']) ? $info['Memory'] : $info; + + return $this->redisEvictionPolicy = $info['maxmemory_policy']; + } + + return $this->redisEvictionPolicy = ''; + } } From 7e38d83ad00399a93ea267a48d9727e377c3e117 Mon Sep 17 00:00:00 2001 From: Antoine Makdessi Date: Fri, 15 Nov 2019 19:14:27 +0100 Subject: [PATCH 27/42] Link the right file depending on the new version --- UPGRADE-4.0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 8d41f32658c58..f970041949e5b 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -26,8 +26,8 @@ file and directory structure of your application: Then, upgrade the contents of your console script and your front controller: -* `bin/console`: https://github.com/symfony/recipes/blob/master/symfony/console/3.3/bin/console -* `public/index.php`: https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/3.3/public/index.php +* `bin/console`: https://github.com/symfony/recipes/blob/master/symfony/console/4.4/bin/console +* `public/index.php`: https://github.com/symfony/recipes/blob/master/symfony/framework-bundle/4.4/public/index.php Lastly, read the following article to add Symfony Flex to your application and upgrade the configuration files: https://symfony.com/doc/current/setup/flex.html From 51c5f69274b0a0375b049fc34a4336ec80b49b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Broutier?= Date: Sat, 16 Nov 2019 12:20:14 +0100 Subject: [PATCH 28/42] Fix MySQL column type definition. Fix wrong MySQL column type definition causing Numeric value out of range exception. Ref #34409 --- .../Session/Storage/Handler/PdoSessionHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index f9e5d1e8f04d8..c9d47b6ed7c27 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -218,7 +218,7 @@ public function createTable() // - trailing space removal // - case-insensitivity // - language processing like é == e - $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol MEDIUMINT NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB"; + $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8_bin, ENGINE = InnoDB"; break; case 'sqlite': $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; From 585216a8e8f38380a9c7a65f97fd899798ed4001 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 16 Nov 2019 13:02:38 +0100 Subject: [PATCH 29/42] [HttpKernel] Flatten "exception" controller argument if not typed --- .../EventListener/ErrorListener.php | 2 +- .../Tests/EventListener/ErrorListenerTest.php | 28 +++++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php b/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php index d8152edd22de7..77da3ce3e7a86 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php @@ -99,7 +99,7 @@ public function onControllerArguments(ControllerArgumentsEvent $event) $r = new \ReflectionFunction(\Closure::fromCallable($event->getController())); $r = $r->getParameters()[$k] ?? null; - if ($r && $r->hasType() && FlattenException::class === $r->getType()->getName()) { + if ($r && (!$r->hasType() || FlattenException::class === $r->getType()->getName())) { $arguments = $event->getArguments(); $arguments[$k] = FlattenException::createFromThrowable($e); $event->setArguments($arguments); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ErrorListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ErrorListenerTest.php index ae7149199f963..cdf6874f359b2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ErrorListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ErrorListenerTest.php @@ -13,8 +13,8 @@ use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\ErrorHandler\Exception\FlattenException; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; @@ -158,12 +158,11 @@ public function testCSPHeaderIsRemoved() $this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed'); } - public function testOnControllerArguments() + /** + * @dataProvider controllerProvider + */ + public function testOnControllerArguments(callable $controller) { - $controller = function (FlattenException $exception) { - return new Response('OK: '.$exception->getMessage()); - }; - $listener = new ErrorListener($controller, $this->createMock(LoggerInterface::class), true); $kernel = $this->createMock(HttpKernelInterface::class); @@ -181,6 +180,23 @@ public function testOnControllerArguments() $this->assertSame('OK: foo', $event->getResponse()->getContent()); } + + public function controllerProvider() + { + yield [function (FlattenException $exception) { + return new Response('OK: '.$exception->getMessage()); + }]; + + yield [function ($exception) { + $this->assertInstanceOf(FlattenException::class, $exception); + + return new Response('OK: '.$exception->getMessage()); + }]; + + yield [function (\Throwable $exception) { + return new Response('OK: '.$exception->getMessage()); + }]; + } } class TestLogger extends Logger implements DebugLoggerInterface From 4d9b6f1bbd86092b76ab279464da3f71e3fa335a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 16 Nov 2019 16:17:02 +0100 Subject: [PATCH 30/42] [HttpFoundation] fix docblock --- .../Session/Storage/Handler/RedisSessionHandler.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php index 46ca6796d8ebb..8ebc5bd8ee75d 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php @@ -34,8 +34,7 @@ class RedisSessionHandler extends AbstractSessionHandler * List of available options: * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server. * - * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy $redis - * @param array $options An associative array of options + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis * * @throws \InvalidArgumentException When unsupported client or options are passed */ From eaca085aa4ec40b51f0591de411f840481319972 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 16 Nov 2019 16:50:12 +0100 Subject: [PATCH 31/42] [SecurityBundle] fix failing test --- .../SecurityBundle/Tests/Functional/SwitchUserTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php index 31f99da2a08f2..722bef0f78628 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php @@ -25,6 +25,10 @@ public function testSwitchUser($originalUser, $targetUser, $expectedUser, $expec $client->request('GET', '/profile?_switch_user='.$targetUser); + if ('user_does_not_exist' === $targetUser && 403 === $expectedStatus && 500 === $client->getResponse()->getStatusCode()) { + $expectedStatus = 500; // 403 is generated by Symfony >= 4.3.8 + } + $this->assertEquals($expectedStatus, $client->getResponse()->getStatusCode()); $this->assertEquals($expectedUser, $client->getProfile()->getCollector('security')->getUser()); } @@ -68,7 +72,7 @@ public function getTestParameters() return [ 'unauthorized_user_cannot_switch' => ['user_cannot_switch_1', 'user_cannot_switch_1', 'user_cannot_switch_1', 403], 'authorized_user_can_switch' => ['user_can_switch', 'user_cannot_switch_1', 'user_cannot_switch_1', 200], - 'authorized_user_cannot_switch_to_non_existent' => ['user_can_switch', 'user_does_not_exist', 'user_can_switch', 500], + 'authorized_user_cannot_switch_to_non_existent' => ['user_can_switch', 'user_does_not_exist', 'user_can_switch', 403], 'authorized_user_can_switch_to_himself' => ['user_can_switch', 'user_can_switch', 'user_can_switch', 200], ]; } From 5c1f5594f5104a97eba28cc9c49e00e78ccdc401 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 16 Nov 2019 10:57:45 +0100 Subject: [PATCH 32/42] catch exceptions when using PDO directly --- src/Symfony/Component/Cache/Traits/PdoTrait.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index ec34e72fb530a..b636e7565b2cd 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -159,6 +159,8 @@ public function prune() $delete = $this->getConnection()->prepare($deleteSql); } catch (TableNotFoundException $e) { return true; + } catch (\PDOException $e) { + return true; } $delete->bindValue(':time', time(), \PDO::PARAM_INT); @@ -169,6 +171,8 @@ public function prune() return $delete->execute(); } catch (TableNotFoundException $e) { return true; + } catch (\PDOException $e) { + return true; } } @@ -244,6 +248,7 @@ protected function doClear($namespace) try { $conn->exec($sql); } catch (TableNotFoundException $e) { + } catch (\PDOException $e) { } return true; @@ -260,6 +265,7 @@ protected function doDelete(array $ids) $stmt = $this->getConnection()->prepare($sql); $stmt->execute(array_values($ids)); } catch (TableNotFoundException $e) { + } catch (\PDOException $e) { } return true; @@ -316,6 +322,11 @@ protected function doSave(array $values, $lifetime) $this->createTable(); } $stmt = $conn->prepare($sql); + } catch (\PDOException $e) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt = $conn->prepare($sql); } if ('sqlsrv' === $driver || 'oci' === $driver) { @@ -350,6 +361,11 @@ protected function doSave(array $values, $lifetime) $this->createTable(); } $stmt->execute(); + } catch (\PDOException $e) { + if (!$conn->inTransaction() || \in_array($this->driver, ['pgsql', 'sqlite', 'sqlsrv'], true)) { + $this->createTable(); + } + $stmt->execute(); } if (null === $driver && !$stmt->rowCount()) { try { From fe15f51d4dd428538a9b62de32ba3c85b628df9f Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Thu, 14 Nov 2019 13:59:57 +0100 Subject: [PATCH 33/42] [DoctrineBridge] Improve queries parameters display in Profiler --- .../DataCollector/DoctrineDataCollector.php | 68 ++++++++++++++---- .../DataCollector/ObjectParameter.php | 54 ++++++++++++++ .../DoctrineDataCollectorTest.php | 70 ++++++++++++++++--- 3 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php diff --git a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php index 871eeee97dfc4..b184a7163d45a 100644 --- a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php +++ b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php @@ -18,6 +18,8 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Cloner\Stub; /** * DoctrineDataCollector. @@ -121,6 +123,38 @@ public function getName() return 'db'; } + /** + * {@inheritdoc} + */ + protected function getCasters() + { + return parent::getCasters() + [ + ObjectParameter::class => static function (ObjectParameter $o, array $a, Stub $s): array { + $s->class = $o->getClass(); + $s->value = $o->getObject(); + + $r = new \ReflectionClass($o->getClass()); + if ($f = $r->getFileName()) { + $s->attr['file'] = $f; + $s->attr['line'] = $r->getStartLine(); + } else { + unset($s->attr['file']); + unset($s->attr['line']); + } + + if ($error = $o->getError()) { + return [Caster::PREFIX_VIRTUAL.'⚠' => $error->getMessage()]; + } + + if ($o->isStringable()) { + return [Caster::PREFIX_VIRTUAL.'__toString()' => (string) $o->getObject()]; + } + + return [Caster::PREFIX_VIRTUAL.'⚠' => sprintf('Object of class "%s" could not be converted to string.', $o->getClass())]; + }, + ]; + } + private function sanitizeQueries(string $connectionName, array $queries): array { foreach ($queries as $i => $query) { @@ -133,6 +167,7 @@ private function sanitizeQueries(string $connectionName, array $queries): array private function sanitizeQuery(string $connectionName, array $query): array { $query['explainable'] = true; + $query['runnable'] = true; if (null === $query['params']) { $query['params'] = []; } @@ -143,6 +178,7 @@ private function sanitizeQuery(string $connectionName, array $query): array $query['types'] = []; } foreach ($query['params'] as $j => $param) { + $e = null; if (isset($query['types'][$j])) { // Transform the param according to the type $type = $query['types'][$j]; @@ -154,18 +190,19 @@ private function sanitizeQuery(string $connectionName, array $query): array try { $param = $type->convertToDatabaseValue($param, $this->registry->getConnection($connectionName)->getDatabasePlatform()); } catch (\TypeError $e) { - // Error thrown while processing params, query is not explainable. - $query['explainable'] = false; } catch (ConversionException $e) { - $query['explainable'] = false; } } } - list($query['params'][$j], $explainable) = $this->sanitizeParam($param); + list($query['params'][$j], $explainable, $runnable) = $this->sanitizeParam($param, $e); if (!$explainable) { $query['explainable'] = false; } + + if (!$runnable) { + $query['runnable'] = false; + } } $query['params'] = $this->cloneVar($query['params']); @@ -180,32 +217,33 @@ private function sanitizeQuery(string $connectionName, array $query): array * indicating if the original value was kept (allowing to use the sanitized * value to explain the query). */ - private function sanitizeParam($var): array + private function sanitizeParam($var, ?\Throwable $error): array { if (\is_object($var)) { - $className = \get_class($var); + return [$o = new ObjectParameter($var, $error), false, $o->isStringable() && !$error]; + } - return method_exists($var, '__toString') ? - [sprintf('/* Object(%s): */"%s"', $className, $var->__toString()), false] : - [sprintf('/* Object(%s) */', $className), false]; + if ($error) { + return ['⚠ '.$error->getMessage(), false, false]; } if (\is_array($var)) { $a = []; - $original = true; + $explainable = $runnable = true; foreach ($var as $k => $v) { - list($value, $orig) = $this->sanitizeParam($v); - $original = $original && $orig; + list($value, $e, $r) = $this->sanitizeParam($v, null); + $explainable = $explainable && $e; + $runnable = $runnable && $r; $a[$k] = $value; } - return [$a, $original]; + return [$a, $explainable, $runnable]; } if (\is_resource($var)) { - return [sprintf('/* Resource(%s) */', get_resource_type($var)), false]; + return [sprintf('/* Resource(%s) */', get_resource_type($var)), false, false]; } - return [$var, true]; + return [$var, true, true]; } } diff --git a/src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php b/src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php new file mode 100644 index 0000000000000..26bdb7ff267d0 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/DataCollector/ObjectParameter.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\DataCollector; + +final class ObjectParameter +{ + private $object; + private $error; + private $stringable; + private $class; + + /** + * @param object $object + */ + public function __construct($object, ?\Throwable $error) + { + $this->object = $object; + $this->error = $error; + $this->stringable = \is_callable([$object, '__toString']); + $this->class = \get_class($object); + } + + /** + * @return object + */ + public function getObject() + { + return $this->object; + } + + public function getError(): ?\Throwable + { + return $this->error; + } + + public function isStringable(): bool + { + return $this->stringable; + } + + public function getClass(): string + { + return $this->class; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php index e6547f3844132..13a6c70669eeb 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\CliDumper; class DoctrineDataCollectorTest extends TestCase { @@ -74,7 +75,7 @@ public function testCollectTime() /** * @dataProvider paramProvider */ - public function testCollectQueries($param, $types, $expected, $explainable) + public function testCollectQueries($param, $types, $expected, $explainable, bool $runnable = true) { $queries = [ ['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1], @@ -83,8 +84,19 @@ public function testCollectQueries($param, $types, $expected, $explainable) $c->collect(new Request(), new Response()); $collectedQueries = $c->getQueries(); - $this->assertEquals($expected, $collectedQueries['default'][0]['params'][0]); + + $collectedParam = $collectedQueries['default'][0]['params'][0]; + if ($collectedParam instanceof Data) { + $dumper = new CliDumper($out = fopen('php://memory', 'r+b')); + $dumper->setColors(false); + $collectedParam->dump($dumper); + $this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true)); + } else { + $this->assertEquals($expected, $collectedParam); + } + $this->assertEquals($explainable, $collectedQueries['default'][0]['explainable']); + $this->assertSame($runnable, $collectedQueries['default'][0]['runnable']); } public function testCollectQueryWithNoParams() @@ -100,9 +112,11 @@ public function testCollectQueryWithNoParams() $this->assertInstanceOf(Data::class, $collectedQueries['default'][0]['params']); $this->assertEquals([], $collectedQueries['default'][0]['params']->getValue()); $this->assertTrue($collectedQueries['default'][0]['explainable']); + $this->assertTrue($collectedQueries['default'][0]['runnable']); $this->assertInstanceOf(Data::class, $collectedQueries['default'][1]['params']); $this->assertEquals([], $collectedQueries['default'][1]['params']->getValue()); $this->assertTrue($collectedQueries['default'][1]['explainable']); + $this->assertTrue($collectedQueries['default'][1]['runnable']); } public function testCollectQueryWithNoTypes() @@ -134,7 +148,7 @@ public function testReset() /** * @dataProvider paramProvider */ - public function testSerialization($param, $types, $expected, $explainable) + public function testSerialization($param, $types, $expected, $explainable, bool $runnable = true) { $queries = [ ['sql' => 'SELECT * FROM table1 WHERE field1 = ?1', 'params' => [$param], 'types' => $types, 'executionMS' => 1], @@ -144,8 +158,19 @@ public function testSerialization($param, $types, $expected, $explainable) $c = unserialize(serialize($c)); $collectedQueries = $c->getQueries(); - $this->assertEquals($expected, $collectedQueries['default'][0]['params'][0]); + + $collectedParam = $collectedQueries['default'][0]['params'][0]; + if ($collectedParam instanceof Data) { + $dumper = new CliDumper($out = fopen('php://memory', 'r+b')); + $dumper->setColors(false); + $collectedParam->dump($dumper); + $this->assertStringMatchesFormat($expected, print_r(stream_get_contents($out, -1, 0), true)); + } else { + $this->assertEquals($expected, $collectedParam); + } + $this->assertEquals($explainable, $collectedQueries['default'][0]['explainable']); + $this->assertSame($runnable, $collectedQueries['default'][0]['runnable']); } public function paramProvider() @@ -156,19 +181,46 @@ public function paramProvider() [true, [], true, true], [null, [], null, true], [new \DateTime('2011-09-11'), ['date'], '2011-09-11', true], - [fopen(__FILE__, 'r'), [], '/* Resource(stream) */', false], - [new \stdClass(), [], '/* Object(stdClass) */', false], + [fopen(__FILE__, 'r'), [], '/* Resource(stream) */', false, false], + [ + new \stdClass(), + [], + <<=')) { - $tests[] = ['this is not a date', ['date'], 'this is not a date', false]; - $tests[] = [new \stdClass(), ['date'], '/* Object(stdClass) */', false]; + $tests[] = ['this is not a date', ['date'], "⚠ Could not convert PHP value 'this is not a date' of type 'string' to type 'date'. Expected one of the following types: null, DateTime", false, false]; + $tests[] = [ + new \stdClass(), + ['date'], + << Date: Sat, 16 Nov 2019 08:58:15 -1000 Subject: [PATCH 34/42] Drop useless executable bit --- .../Component/HttpClient/DependencyInjection/HttpClientPass.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/Symfony/Component/HttpClient/DependencyInjection/HttpClientPass.php diff --git a/src/Symfony/Component/HttpClient/DependencyInjection/HttpClientPass.php b/src/Symfony/Component/HttpClient/DependencyInjection/HttpClientPass.php old mode 100755 new mode 100644 From bd0637ebe4e8779b6b7b5b447ca4fd3d5ff44149 Mon Sep 17 00:00:00 2001 From: Mark Beech Date: Wed, 13 Nov 2019 20:07:22 +0000 Subject: [PATCH 35/42] [HttpFoundation] Allow redirecting to URLs that contain a semicolon --- src/Symfony/Component/HttpFoundation/RedirectResponse.php | 2 +- .../Component/HttpFoundation/Tests/RedirectResponseTest.php | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/RedirectResponse.php b/src/Symfony/Component/HttpFoundation/RedirectResponse.php index 4e3cb4f77b28b..a19efba3e3d5e 100644 --- a/src/Symfony/Component/HttpFoundation/RedirectResponse.php +++ b/src/Symfony/Component/HttpFoundation/RedirectResponse.php @@ -93,7 +93,7 @@ public function setTargetUrl($url) - + Redirecting to %1$s diff --git a/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php index e1ff3bf2bdb98..2bbf5aa1aea5a 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php @@ -20,10 +20,7 @@ public function testGenerateMetaRedirect() { $response = new RedirectResponse('foo.bar'); - $this->assertEquals(1, preg_match( - '##', - preg_replace(['/\s+/', '/\'/'], [' ', '"'], $response->getContent()) - )); + $this->assertRegExp('##', preg_replace('/\s+/', ' ', $response->getContent())); } public function testRedirectResponseConstructorNullUrl() From e75e01dda4ddf18aeecf2bee1c780b11bab160fd Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 15 Nov 2019 16:11:40 +0100 Subject: [PATCH 36/42] [FrameworkBundle] Remove project dir from Translator cache vary scanned directories --- .../DependencyInjection/FrameworkExtension.php | 9 ++++++++- .../DependencyInjection/FrameworkExtensionTest.php | 2 ++ .../Tests/Translation/TranslatorTest.php | 14 +++++++++----- .../FrameworkBundle/Translation/Translator.php | 10 +++++----- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index a913f4f93db40..2ad1566a25aa8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1184,11 +1184,18 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder $files[$locale][] = (string) $file; } + $projectDir = $container->getParameter('kernel.project_dir'); + $options = array_merge( $translator->getArgument(4), [ 'resource_files' => $files, - 'scanned_directories' => array_merge($dirs, $nonExistingDirs), + 'scanned_directories' => $scannedDirectories = array_merge($dirs, $nonExistingDirs), + 'cache_vary' => [ + 'scanned_directories' => array_map(static function (string $dir) use ($projectDir): string { + return 0 === strpos($dir, $projectDir.'/') ? substr($dir, 1 + \strlen($projectDir)) : $dir; + }, $scannedDirectories), + ], ] ); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 5f2e007ddbcd4..45a3c02e76c3c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -824,6 +824,8 @@ function ($directory) { ); $this->assertNotEmpty($nonExistingDirectories, 'FrameworkBundle should pass non existing directories to Translator'); + + $this->assertSame('Fixtures/translations', $options['cache_vary']['scanned_directories'][3]); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index cd3f3d9fba858..5eaf901d16027 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -255,8 +255,10 @@ public function testCachedCatalogueIsReDumpedWhenScannedDirectoriesChange() __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', ], ], - 'scanned_directories' => [ - __DIR__.'/../Fixtures/Resources/translations/', + 'cache_vary' => [ + 'scanned_directories' => [ + '/Fixtures/Resources/translations/', + ], ], ], 'yml'); @@ -271,9 +273,11 @@ public function testCachedCatalogueIsReDumpedWhenScannedDirectoriesChange() __DIR__.'/../Fixtures/Resources/translations2/ccc.fr.yml', ], ], - 'scanned_directories' => [ - __DIR__.'/../Fixtures/Resources/translations/', - __DIR__.'/../Fixtures/Resources/translations2/', + 'cache_vary' => [ + 'scanned_directories' => [ + '/Fixtures/Resources/translations/', + '/Fixtures/Resources/translations2/', + ], ], ], 'yml'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index f718c8d0157bc..155372ee136f4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -34,6 +34,7 @@ class Translator extends BaseTranslator implements WarmableInterface 'debug' => false, 'resource_files' => [], 'scanned_directories' => [], + 'cache_vary' => [], ]; /** @@ -61,9 +62,10 @@ class Translator extends BaseTranslator implements WarmableInterface * * Available options: * - * * cache_dir: The cache directory (or null to disable caching) - * * debug: Whether to enable debugging or not (false by default) + * * cache_dir: The cache directory (or null to disable caching) + * * debug: Whether to enable debugging or not (false by default) * * resource_files: List of translation resources available grouped by locale. + * * cache_vary: An array of data that is serialized to generate the cached catalogue name. * * @throws InvalidArgumentException */ @@ -82,9 +84,7 @@ public function __construct(ContainerInterface $container, MessageFormatterInter $this->resourceFiles = $this->options['resource_files']; $this->scannedDirectories = $this->options['scanned_directories']; - parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug'], [ - 'scanned_directories' => $this->scannedDirectories, - ]); + parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug'], $this->options['cache_vary']); } /** From 4a9d947b1acdfa7c6a1d590fe300cca6d1ff76d5 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Sat, 16 Nov 2019 03:22:35 +0600 Subject: [PATCH 37/42] [HttpFoundation] Added possibility to configure expiration time in redis session handler --- .../Storage/Handler/RedisSessionHandler.php | 15 +++++++--- .../AbstractRedisSessionHandlerTestCase.php | 30 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php index 40c209341eb42..f11c8c4d62e41 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/RedisSessionHandler.php @@ -30,9 +30,15 @@ class RedisSessionHandler extends AbstractSessionHandler */ private $prefix; + /** + * @var int Time to live in seconds + */ + private $ttl; + /** * List of available options: - * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server. + * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server + * * ttl: The time to live in seconds. * * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy $redis * @@ -51,12 +57,13 @@ public function __construct($redis, array $options = []) throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); } - if ($diff = array_diff(array_keys($options), ['prefix'])) { + if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); } $this->redis = $redis; $this->prefix = $options['prefix'] ?? 'sf_s'; + $this->ttl = $options['ttl'] ?? (int) ini_get('session.gc_maxlifetime'); } /** @@ -72,7 +79,7 @@ protected function doRead($sessionId): string */ protected function doWrite($sessionId, $data): bool { - $result = $this->redis->setEx($this->prefix.$sessionId, (int) ini_get('session.gc_maxlifetime'), $data); + $result = $this->redis->setEx($this->prefix.$sessionId, $this->ttl, $data); return $result && !$result instanceof ErrorInterface; } @@ -108,6 +115,6 @@ public function gc($maxlifetime): bool */ public function updateTimestamp($sessionId, $data) { - return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ini_get('session.gc_maxlifetime')); + return (bool) $this->redis->expire($this->prefix.$sessionId, $this->ttl); } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php index 6a15a06873e25..8828be666f2dc 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php @@ -139,7 +139,37 @@ public function getOptionFixtures(): array { return [ [['prefix' => 'session'], true], + [['ttl' => 1000], true], + [['prefix' => 'sfs', 'ttl' => 1000], true], [['prefix' => 'sfs', 'foo' => 'bar'], false], + [['ttl' => 'sfs', 'foo' => 'bar'], false], + ]; + } + + /** + * @dataProvider getTtlFixtures + */ + public function testUseTtlOption(int $ttl) + { + $options = [ + 'prefix' => self::PREFIX, + 'ttl' => $ttl, + ]; + + $handler = new RedisSessionHandler($this->redisClient, $options); + $handler->write('id', 'data'); + $redisTtl = $this->redisClient->ttl(self::PREFIX.'id'); + + $this->assertLessThan($redisTtl, $ttl - 5); + $this->assertGreaterThan($redisTtl, $ttl + 5); + } + + public function getTtlFixtures(): array + { + return [ + ['ttl' => 5000], + ['ttl' => 120], + ['ttl' => 60], ]; } } From c264583f28cfc7129c58e4d5624306064a96af47 Mon Sep 17 00:00:00 2001 From: Valentin Udaltsov Date: Wed, 13 Nov 2019 08:03:57 +0300 Subject: [PATCH 38/42] [Messenger] Perform no deep merging of bus middleware --- .../Bundle/FrameworkBundle/CHANGELOG.md | 3 +- .../DependencyInjection/Configuration.php | 1 + .../DependencyInjection/ConfigurationTest.php | 58 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 60e1e319f719d..0220844b2697d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -17,10 +17,11 @@ CHANGELOG * Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated. * Added new `error_controller` configuration to handle system exceptions * Added sort option for `translation:update` command. - * [BC Break] The `framework.messenger.routing.senders` config key is not deep merged anymore. + * [BC Break] The `framework.messenger.routing.senders` config key is not deeply merged anymore. * Added `secrets:*` commands and `%env(secret:...)%` processor to deal with secrets seamlessly. * Made `framework.session.handler_id` accept a DSN * Marked the `RouterDataCollector` class as `@final`. + * [BC Break] The `framework.messenger.buses..middleware` config key is not deeply merged anymore. 4.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 405aff41d7fed..c99106299a588 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -1293,6 +1293,7 @@ function ($a) { ->defaultTrue() ->end() ->arrayNode('middleware') + ->performNoDeepMerging() ->beforeNormalization() ->ifTrue(function ($v) { return \is_string($v) || (\is_array($v) && !\is_int(key($v))); }) ->then(function ($v) { return [$v]; }) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index f79897a6badd0..a95e649c80c91 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -271,6 +271,64 @@ public function testItShowANiceMessageIfTwoMessengerBusesAreConfiguredButNoDefau ]); } + public function testBusMiddlewareDontMerge() + { + $processor = new Processor(); + $configuration = new Configuration(true); + $config = $processor->processConfiguration($configuration, [ + [ + 'messenger' => [ + 'default_bus' => 'existing_bus', + 'buses' => [ + 'existing_bus' => [ + 'middleware' => 'existing_bus.middleware', + ], + 'common_bus' => [ + 'default_middleware' => false, + 'middleware' => 'common_bus.old_middleware', + ], + ], + ], + ], + [ + 'messenger' => [ + 'buses' => [ + 'common_bus' => [ + 'middleware' => 'common_bus.new_middleware', + ], + 'new_bus' => [ + 'middleware' => 'new_bus.middleware', + ], + ], + ], + ], + ]); + + $this->assertEquals( + [ + 'existing_bus' => [ + 'default_middleware' => true, + 'middleware' => [ + ['id' => 'existing_bus.middleware', 'arguments' => []], + ], + ], + 'common_bus' => [ + 'default_middleware' => false, + 'middleware' => [ + ['id' => 'common_bus.new_middleware', 'arguments' => []], + ], + ], + 'new_bus' => [ + 'default_middleware' => true, + 'middleware' => [ + ['id' => 'new_bus.middleware', 'arguments' => []], + ], + ], + ], + $config['messenger']['buses'] + ); + } + protected static function getBundleDefaultConfig() { return [ From a2c924d77220011c5f5939579677d2a82b69a43d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 17 Nov 2019 11:56:39 +0100 Subject: [PATCH 39/42] [Cache] Disable igbinary on PHP >= 7.4 --- .../Cache/Marshaller/DefaultMarshaller.php | 8 ++++---- .../Tests/Marshaller/DefaultMarshallerTest.php | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/Cache/Marshaller/DefaultMarshaller.php b/src/Symfony/Component/Cache/Marshaller/DefaultMarshaller.php index 196fd625f1fb9..8056090110c41 100644 --- a/src/Symfony/Component/Cache/Marshaller/DefaultMarshaller.php +++ b/src/Symfony/Component/Cache/Marshaller/DefaultMarshaller.php @@ -25,9 +25,9 @@ class DefaultMarshaller implements MarshallerInterface public function __construct(bool $useIgbinarySerialize = null) { if (null === $useIgbinarySerialize) { - $useIgbinarySerialize = \extension_loaded('igbinary') && \PHP_VERSION_ID !== 70400; - } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || \PHP_VERSION_ID === 70400)) { - throw new CacheException('The "igbinary" PHP extension is not '.(\PHP_VERSION_ID === 70400 ? 'compatible with PHP 7.4.0.' : 'loaded.')); + $useIgbinarySerialize = \extension_loaded('igbinary') && \PHP_VERSION_ID < 70400; + } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || \PHP_VERSION_ID >= 70400)) { + throw new CacheException('The "igbinary" PHP extension is not '.(\PHP_VERSION_ID >= 70400 ? 'compatible with PHP 7.4.' : 'loaded.')); } $this->useIgbinarySerialize = $useIgbinarySerialize; } @@ -66,7 +66,7 @@ public function unmarshall(string $value) return null; } static $igbinaryNull; - if ($value === ($igbinaryNull ?? $igbinaryNull = \extension_loaded('igbinary') && \PHP_VERSION_ID !== 70400 ? igbinary_serialize(null) : false)) { + if ($value === ($igbinaryNull ?? $igbinaryNull = \extension_loaded('igbinary') && \PHP_VERSION_ID < 70400 ? igbinary_serialize(null) : false)) { return null; } $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); diff --git a/src/Symfony/Component/Cache/Tests/Marshaller/DefaultMarshallerTest.php b/src/Symfony/Component/Cache/Tests/Marshaller/DefaultMarshallerTest.php index 141291d6e448b..cc94ad15237a0 100644 --- a/src/Symfony/Component/Cache/Tests/Marshaller/DefaultMarshallerTest.php +++ b/src/Symfony/Component/Cache/Tests/Marshaller/DefaultMarshallerTest.php @@ -24,7 +24,7 @@ public function testSerialize() 'b' => function () {}, ]; - $expected = ['a' => \extension_loaded('igbinary') && \PHP_VERSION_ID !== 70400 ? igbinary_serialize(123) : serialize(123)]; + $expected = ['a' => \extension_loaded('igbinary') && \PHP_VERSION_ID < 70400 ? igbinary_serialize(123) : serialize(123)]; $this->assertSame($expected, $marshaller->marshall($values, $failed)); $this->assertSame(['b'], $failed); } @@ -43,8 +43,8 @@ public function testNativeUnserialize() */ public function testIgbinaryUnserialize() { - if (\PHP_VERSION_ID === 70400) { - $this->markTestSkipped('igbinary is not compatible with PHP 7.4.0.'); + if (\PHP_VERSION_ID >= 70400) { + $this->markTestSkipped('igbinary is not compatible with PHP 7.4.'); } $marshaller = new DefaultMarshaller(); @@ -67,8 +67,8 @@ public function testNativeUnserializeNotFoundClass() */ public function testIgbinaryUnserializeNotFoundClass() { - if (\PHP_VERSION_ID === 70400) { - $this->markTestSkipped('igbinary is not compatible with PHP 7.4.0.'); + if (\PHP_VERSION_ID >= 70400) { + $this->markTestSkipped('igbinary is not compatible with PHP 7.4.'); } $this->expectException('DomainException'); @@ -95,8 +95,8 @@ public function testNativeUnserializeInvalid() */ public function testIgbinaryUnserializeInvalid() { - if (\PHP_VERSION_ID === 70400) { - $this->markTestSkipped('igbinary is not compatible with PHP 7.4.0'); + if (\PHP_VERSION_ID >= 70400) { + $this->markTestSkipped('igbinary is not compatible with PHP 7.4.'); } $this->expectException('DomainException'); From d53b91a45af4f83c83e1ed896b5954bc2aa83e75 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 10 Jul 2019 01:47:30 +0200 Subject: [PATCH 40/42] Add conflict rule for Monolog 2. --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 42397d75b851d..9ad5e39ad2ca5 100644 --- a/composer.json +++ b/composer.json @@ -103,6 +103,7 @@ "phpdocumentor/reflection-docblock": "^3.0|^4.0" }, "conflict": { + "monolog/monolog": ">=2", "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", "phpdocumentor/type-resolver": "<0.3.0", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" From 6143defde136a066f6299a65c9375b1224755493 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 17 Nov 2019 18:07:42 +0100 Subject: [PATCH 41/42] Update CHANGELOG for 5.0.0-RC1 --- CHANGELOG-5.0.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG-5.0.md b/CHANGELOG-5.0.md index 9d80521545f0f..255b7812dc71d 100644 --- a/CHANGELOG-5.0.md +++ b/CHANGELOG-5.0.md @@ -7,6 +7,30 @@ in 5.0 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.0.0...v5.0.1 +* 5.0.0-RC1 (2019-11-17) + + * bug #34419 [Cache] Disable igbinary on PHP >= 7.4 (nicolas-grekas) + * bug #34347 [Messenger] Perform no deep merging of bus middleware (vudaltsov) + * bug #34366 [HttpFoundation] Allow redirecting to URLs that contain a semicolon (JayBizzle) + * feature #34405 [HttpFoundation] Added possibility to configure expiration time in redis session handler (mantulo) + * bug #34397 [FrameworkBundle] Remove project dir from Translator cache vary scanned directories (fancyweb) + * bug #34384 [DoctrineBridge] Improve queries parameters display in Profiler (fancyweb) + * bug #34408 [Cache] catch exceptions when using PDO directly (xabbuh) + * bug #34411 [HttpKernel] Flatten "exception" controller argument if not typed (chalasr) + * bug #34410 [HttpFoundation] Fix MySQL column type definition. (jbroutier) + * bug #34403 [Cache] Redis Tag Aware warn on wrong eviction policy (andrerom) + * bug #34400 [HttpKernel] collect bundle classes, not paths (nicolas-grekas) + * bug #34398 [Config] fix id-generation for GlobResource (nicolas-grekas) + * bug #34404 [HttpClient] fix HttpClientDataCollector (nicolas-grekas) + * bug #34396 [Finder] Allow ssh2 stream wrapper for sftp (damienalexandre) + * bug #34383 [DI] Use reproducible entropy to generate env placeholders (nicolas-grekas) + * bug #34389 [WebProfilerBundle] add FrameworkBundle requirement (xabbuh) + * bug #34381 [WebProfilerBundle] Require symfony/twig-bundle (fancyweb) + * bug #34358 [Security] always check the token on non-lazy firewalls (nicolas-grekas, lyrixx) + * bug #34390 [FrameworkBundle] fix wiring of httplug client (nicolas-grekas) + * bug #34369 [FrameworkBundle] Disallow WebProfilerBundle < 4.4 (derrabus) + * bug #34370 [DI] fix detecting singly implemented interfaces (nicolas-grekas) + * 5.0.0-BETA2 (2019-11-13) * bug #34344 [Console] Constant STDOUT might be undefined (nicolas-grekas) From e4cc7cd698a83048f78226e045ea52ae67c45ee7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 17 Nov 2019 18:09:30 +0100 Subject: [PATCH 42/42] Update VERSION for 5.0.0-RC1 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 6c38e9e96dbef..edaf8db5142f1 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -68,12 +68,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - const VERSION = '5.0.0-DEV'; + const VERSION = '5.0.0-RC1'; const VERSION_ID = 50000; const MAJOR_VERSION = 5; const MINOR_VERSION = 0; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = 'RC1'; const END_OF_MAINTENANCE = '07/2020'; const END_OF_LIFE = '07/2020';