From 79fe888072387189e6da105e54a50a9ef8402d70 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 27 Mar 2020 17:16:43 +0100 Subject: [PATCH 01/51] [HttpKernel][LoggerDataCollector] Prevent keys collisions in the sanitized logs processing --- .../HttpKernel/DataCollector/LoggerDataCollector.php | 2 +- .../Tests/DataCollector/LoggerDataCollectorTest.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index 99a9cf23e8398..9c05daa36fe96 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -172,7 +172,7 @@ private function sanitizeLogs($logs) continue; } - $message = $log['message']; + $message = '_'.$log['message']; $exception = $log['context']['exception']; if ($exception instanceof SilencedErrorContext) { diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php index 8b7fbe2a19ea6..b46357ed5585e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php @@ -132,13 +132,15 @@ public function getCollectTestData() [ ['message' => 'foo3', 'context' => ['exception' => new \ErrorException('warning', 0, E_USER_WARNING)], 'priority' => 100, 'priorityName' => 'DEBUG'], ['message' => 'foo3', 'context' => ['exception' => new SilencedErrorContext(E_USER_WARNING, __FILE__, __LINE__)], 'priority' => 100, 'priorityName' => 'DEBUG'], + ['message' => '0', 'context' => ['exception' => new SilencedErrorContext(E_USER_WARNING, __FILE__, __LINE__)], 'priority' => 100, 'priorityName' => 'DEBUG'], ], [ ['message' => 'foo3', 'context' => ['exception' => ['warning', E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG'], ['message' => 'foo3', 'context' => ['exception' => [E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true], + ['message' => '0', 'context' => ['exception' => [E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true], ], 0, - 1, + 2, ]; } } From edcfd600aaba75734838f631ecd5cc60df7b6ac2 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Fri, 27 Mar 2020 20:28:29 +0100 Subject: [PATCH 02/51] [Validator] Fixed calling getters before resolving groups --- .../Validator/Context/ExecutionContext.php | 9 ++++-- .../EntityWithGroupedConstraintOnMethods.php | 27 ++++++++++++++++ .../Validator/RecursiveValidatorTest.php | 24 ++++++++++++++ .../Validator/Validator/LazyProperty.php | 32 +++++++++++++++++++ .../RecursiveContextualValidator.php | 14 +++++++- 5 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/EntityWithGroupedConstraintOnMethods.php create mode 100644 src/Symfony/Component/Validator/Validator/LazyProperty.php diff --git a/src/Symfony/Component/Validator/Context/ExecutionContext.php b/src/Symfony/Component/Validator/Context/ExecutionContext.php index 7ca9caa80fefb..44427c8489cca 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContext.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContext.php @@ -20,6 +20,7 @@ use Symfony\Component\Validator\Mapping\MetadataInterface; use Symfony\Component\Validator\Mapping\PropertyMetadataInterface; use Symfony\Component\Validator\Util\PropertyPath; +use Symfony\Component\Validator\Validator\LazyProperty; use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Validator\Violation\ConstraintViolationBuilder; @@ -187,7 +188,7 @@ public function addViolation($message, array $parameters = []) $parameters, $this->root, $this->propertyPath, - $this->value, + $this->getValue(), null, null, $this->constraint @@ -206,7 +207,7 @@ public function buildViolation($message, array $parameters = []) $parameters, $this->root, $this->propertyPath, - $this->value, + $this->getValue(), $this->translator, $this->translationDomain ); @@ -241,6 +242,10 @@ public function getRoot() */ public function getValue() { + if ($this->value instanceof LazyProperty) { + return $this->value->getPropertyValue(); + } + return $this->value; } diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/EntityWithGroupedConstraintOnMethods.php b/src/Symfony/Component/Validator/Tests/Fixtures/EntityWithGroupedConstraintOnMethods.php new file mode 100644 index 0000000000000..89cae29f050c7 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/EntityWithGroupedConstraintOnMethods.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +class EntityWithGroupedConstraintOnMethods +{ + public $bar; + + public function isValidInFoo() + { + return false; + } + + public function getBar() + { + throw new \Exception('Should not be called'); + } +} diff --git a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php index 8109b6b9bfd4d..31871c3f9a1ed 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php @@ -14,14 +14,19 @@ use Symfony\Component\Translation\IdentityTranslator; use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Collection; +use Symfony\Component\Validator\Constraints\GroupSequence; +use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\ConstraintValidatorFactory; use Symfony\Component\Validator\Context\ExecutionContextFactory; +use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildA; use Symfony\Component\Validator\Tests\Constraints\Fixtures\ChildB; use Symfony\Component\Validator\Tests\Fixtures\Entity; +use Symfony\Component\Validator\Tests\Fixtures\EntityWithGroupedConstraintOnMethods; use Symfony\Component\Validator\Validator\RecursiveValidator; class RecursiveValidatorTest extends AbstractTest @@ -117,6 +122,25 @@ public function testCollectionConstraintValidateAllGroupsForNestedConstraints() $this->assertInstanceOf(NotBlank::class, $violations->get(1)->getConstraint()); } + public function testGroupedMethodConstraintValidateInSequence() + { + $metadata = new ClassMetadata(EntityWithGroupedConstraintOnMethods::class); + $metadata->addPropertyConstraint('bar', new NotNull(['groups' => 'Foo'])); + $metadata->addGetterMethodConstraint('validInFoo', 'isValidInFoo', new IsTrue(['groups' => 'Foo'])); + $metadata->addGetterMethodConstraint('bar', 'getBar', new NotNull(['groups' => 'Bar'])); + + $this->metadataFactory->addMetadata($metadata); + + $entity = new EntityWithGroupedConstraintOnMethods(); + $groups = new GroupSequence(['EntityWithGroupedConstraintOnMethods', 'Foo', 'Bar']); + + $violations = $this->validator->validate($entity, null, $groups); + + $this->assertCount(2, $violations); + $this->assertInstanceOf(NotNull::class, $violations->get(0)->getConstraint()); + $this->assertInstanceOf(IsTrue::class, $violations->get(1)->getConstraint()); + } + public function testAllConstraintValidateAllGroupsForNestedConstraints() { $this->metadata->addPropertyConstraint('data', new All(['constraints' => [ diff --git a/src/Symfony/Component/Validator/Validator/LazyProperty.php b/src/Symfony/Component/Validator/Validator/LazyProperty.php new file mode 100644 index 0000000000000..a0799963c150f --- /dev/null +++ b/src/Symfony/Component/Validator/Validator/LazyProperty.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Validator; + +/** + * A wrapper for a callable initializing a property from a getter. + * + * @internal + */ +class LazyProperty +{ + private $propertyValueCallback; + + public function __construct(\Closure $propertyValueCallback) + { + $this->propertyValueCallback = $propertyValueCallback; + } + + public function getPropertyValue() + { + return \call_user_func($this->propertyValueCallback); + } +} diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index dc139c36d4254..dd96247b4cf85 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -26,6 +26,7 @@ use Symfony\Component\Validator\Mapping\ClassMetadataInterface; use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Mapping\GenericMetadata; +use Symfony\Component\Validator\Mapping\GetterMetadata; use Symfony\Component\Validator\Mapping\MetadataInterface; use Symfony\Component\Validator\Mapping\PropertyMetadataInterface; use Symfony\Component\Validator\Mapping\TraversalStrategy; @@ -534,7 +535,13 @@ private function validateClassNode($object, $cacheKey, ClassMetadataInterface $m throw new UnsupportedMetadataException(sprintf('The property metadata instances should implement "Symfony\Component\Validator\Mapping\PropertyMetadataInterface", got: "%s".', \is_object($propertyMetadata) ? \get_class($propertyMetadata) : \gettype($propertyMetadata))); } - $propertyValue = $propertyMetadata->getPropertyValue($object); + if ($propertyMetadata instanceof GetterMetadata) { + $propertyValue = new LazyProperty(static function () use ($propertyMetadata, $object) { + return $propertyMetadata->getPropertyValue($object); + }); + } else { + $propertyValue = $propertyMetadata->getPropertyValue($object); + } $this->validateGenericNode( $propertyValue, @@ -798,6 +805,11 @@ private function validateInGroup($value, $cacheKey, MetadataInterface $metadata, $validator = $this->validatorFactory->getInstance($constraint); $validator->initialize($context); + + if ($value instanceof LazyProperty) { + $value = $value->getPropertyValue(); + } + $validator->validate($value, $constraint); } } From 2555bfffa9f166d6589f31c5ccd711cd55267fc5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Mar 2020 08:41:06 +0200 Subject: [PATCH 03/51] bumped Symfony version to 3.4.40 --- 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 7193c8b935b6d..9422d90e9ee9b 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.39'; - const VERSION_ID = 30439; + const VERSION = '3.4.40-DEV'; + const VERSION_ID = 30440; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 39; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 40; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From 35644cf8dd4779820b0b3bf8dd8e1423d07bde17 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 30 Mar 2020 10:15:56 +0200 Subject: [PATCH 04/51] [FrameworkBundle] revert to legacy wiring of the session when circular refs are detected --- .../Compiler/SessionPass.php | 50 +++++++++++++++++++ .../FrameworkBundle/FrameworkBundle.php | 2 + .../Compiler/SessionPassTest.php | 44 ++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SessionPass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SessionPassTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SessionPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SessionPass.php new file mode 100644 index 0000000000000..0f4950615fbce --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SessionPass.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @internal to be removed in 6.0 + */ +class SessionPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('session')) { + return; + } + + $bags = [ + 'session.flash_bag' => $container->hasDefinition('session.flash_bag') ? $container->getDefinition('session.flash_bag') : null, + 'session.attribute_bag' => $container->hasDefinition('session.attribute_bag') ? $container->getDefinition('session.attribute_bag') : null, + ]; + + foreach ($container->getDefinition('session')->getArguments() as $v) { + if (!$v instanceof Reference || !isset($bags[$bag = (string) $v]) || !\is_array($factory = $bags[$bag]->getFactory())) { + continue; + } + + if ([0, 1] !== array_keys($factory) || !$factory[0] instanceof Reference || 'session' !== (string) $factory[0]) { + continue; + } + + if ('get'.ucfirst(substr($bag, 8, -4)).'Bag' !== $factory[1]) { + continue; + } + + $bags[$bag]->setFactory(null); + } + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index b472275ff530a..f8bf78d859054 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -22,6 +22,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SessionPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; @@ -125,6 +126,7 @@ public function build(ContainerBuilder $container) $this->addCompilerPassIfExists($container, FormPass::class); $container->addCompilerPass(new WorkflowGuardListenerPass()); $container->addCompilerPass(new ResettableServicePass()); + $container->addCompilerPass(new SessionPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SessionPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SessionPassTest.php new file mode 100644 index 0000000000000..afc6f9b4b2577 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SessionPassTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SessionPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +class SessionPassTest extends TestCase +{ + public function testProcess() + { + $arguments = [ + new Reference('session.flash_bag'), + new Reference('session.attribute_bag'), + ]; + $container = new ContainerBuilder(); + $container + ->register('session') + ->setArguments($arguments); + $container + ->register('session.flash_bag') + ->setFactory([new Reference('session'), 'getFlashBag']); + $container + ->register('session.attribute_bag') + ->setFactory([new Reference('session'), 'getAttributeBag']); + + (new SessionPass())->process($container); + + $this->assertSame($arguments, $container->getDefinition('session')->getArguments()); + $this->assertNull($container->getDefinition('session.flash_bag')->getFactory()); + $this->assertNull($container->getDefinition('session.attribute_bag')->getFactory()); + } +} From a696d1f3afda2c1cf63218975ce1066a9c8a349c Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Sat, 28 Mar 2020 17:27:16 +0100 Subject: [PATCH 05/51] [Security/Http] Allow setting cookie security settings for delete_cookies --- .../DependencyInjection/MainConfiguration.php | 2 ++ .../Security/Http/Logout/CookieClearingLogoutHandler.php | 2 +- .../Http/Tests/Logout/CookieClearingLogoutHandlerTest.php | 7 ++++++- src/Symfony/Component/Security/Http/composer.json | 2 +- src/Symfony/Component/Security/composer.json | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index df96cf2db78f5..1020c86e8e583 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -273,6 +273,8 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->children() ->scalarNode('path')->defaultNull()->end() ->scalarNode('domain')->defaultNull()->end() + ->scalarNode('secure')->defaultFalse()->end() + ->scalarNode('samesite')->defaultNull()->end() ->end() ->end() ->end() diff --git a/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php b/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php index 2aa7c732b976a..9367a62b33bdf 100644 --- a/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php +++ b/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php @@ -38,7 +38,7 @@ public function __construct(array $cookies) public function logout(Request $request, Response $response, TokenInterface $token) { foreach ($this->cookies as $cookieName => $cookieData) { - $response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain']); + $response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain'], isset($cookieData['secure']) ? $cookieData['secure'] : false, true, isset($cookieData['samesite']) ? $cookieData['samesite'] : null); } } } diff --git a/src/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php index 8dcc10338b768..f2407fcb3fdd5 100644 --- a/src/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Logout/CookieClearingLogoutHandlerTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Security\Http\Tests\Logout; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; @@ -25,7 +26,7 @@ public function testLogout() $response = new Response(); $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); - $handler = new CookieClearingLogoutHandler(['foo' => ['path' => '/foo', 'domain' => 'foo.foo'], 'foo2' => ['path' => null, 'domain' => null]]); + $handler = new CookieClearingLogoutHandler(['foo' => ['path' => '/foo', 'domain' => 'foo.foo', 'secure' => true, 'samesite' => Cookie::SAMESITE_STRICT], 'foo2' => ['path' => null, 'domain' => null]]); $cookies = $response->headers->getCookies(); $this->assertCount(0, $cookies); @@ -39,12 +40,16 @@ public function testLogout() $this->assertEquals('foo', $cookie->getName()); $this->assertEquals('/foo', $cookie->getPath()); $this->assertEquals('foo.foo', $cookie->getDomain()); + $this->assertEquals(Cookie::SAMESITE_STRICT, $cookie->getSameSite()); + $this->assertTrue($cookie->isSecure()); $this->assertTrue($cookie->isCleared()); $cookie = $cookies['']['/']['foo2']; $this->assertStringStartsWith('foo2', $cookie->getName()); $this->assertEquals('/', $cookie->getPath()); $this->assertNull($cookie->getDomain()); + $this->assertNull($cookie->getSameSite()); + $this->assertFalse($cookie->isSecure()); $this->assertTrue($cookie->isCleared()); } } diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index 9ede332facfa0..fcf018c54e511 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -19,7 +19,7 @@ "php": "^5.5.9|>=7.0.8", "symfony/security-core": "~3.2|~4.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~3.4.39|^4.4.6", "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index 5d50f82021292..a756b4aa4c776 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^2.8.31|~3.3.13|~3.4|~4.0", + "symfony/http-foundation": "~3.4.39|^4.4.6", "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", From e1c48f3449edb4ccf7815757ad30506351f810cd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Mar 2020 13:26:49 +0200 Subject: [PATCH 06/51] Fix versions --- src/Symfony/Component/Security/Http/composer.json | 2 +- src/Symfony/Component/Security/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index fcf018c54e511..449e07ed8f680 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -19,7 +19,7 @@ "php": "^5.5.9|>=7.0.8", "symfony/security-core": "~3.2|~4.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~3.4.39|^4.4.6", + "symfony/http-foundation": "~3.4.40|^4.4.7", "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index a756b4aa4c776..44eedcc9de12e 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~3.4.39|^4.4.6", + "symfony/http-foundation": "~3.4.40|^4.4.7", "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", From bbc08d7a9e74a10458c46ae4fb7824cd67e03100 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Apr 2020 07:33:51 +0200 Subject: [PATCH 07/51] Fix wrong namespaces --- .../Fixtures/CustomPathBundle/src/CustomPathBundle.php | 2 +- .../DependencyInjection/Fixtures/TestBundle/TestBundle.php | 2 +- .../PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/src/CustomPathBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/src/CustomPathBundle.php index 166b606a459e2..a4049b8690522 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/src/CustomPathBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/CustomPathBundle/src/CustomPathBundle.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\FrameworkBundle\Tests; +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\CustomPathBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php index 2f090b2de8d53..c58b25066bf4a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/TestBundle/TestBundle.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\FrameworkBundle\Tests; +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\TestBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php index f4f9e9dc77e29..4c19a86b43767 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\PropertyInfo\Tests\PhpDocExtractor; +namespace Symfony\Component\PropertyInfo\Tests\Extractor; use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; From b4df2b9dff8510772de418e70688b84ce1445b1c Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 1 Apr 2020 19:12:29 +0200 Subject: [PATCH 08/51] [PropertyInfo][ReflectionExtractor] Check the array mutator prefixes last when the property is singular --- .../PropertyInfo/Extractor/ReflectionExtractor.php | 10 +++++++++- .../Tests/Extractor/ReflectionExtractorTest.php | 4 ++++ .../Component/PropertyInfo/Tests/Fixtures/Dummy.php | 8 ++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index dcb06ee192249..3306946a9b337 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -61,6 +61,9 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp */ private $arrayMutatorPrefixes; + private $arrayMutatorPrefixesFirst; + private $arrayMutatorPrefixesLast; + /** * @param string[]|null $mutatorPrefixes * @param string[]|null $accessorPrefixes @@ -72,6 +75,9 @@ public function __construct(array $mutatorPrefixes = null, array $accessorPrefix $this->mutatorPrefixes = null !== $mutatorPrefixes ? $mutatorPrefixes : self::$defaultMutatorPrefixes; $this->accessorPrefixes = null !== $accessorPrefixes ? $accessorPrefixes : self::$defaultAccessorPrefixes; $this->arrayMutatorPrefixes = null !== $arrayMutatorPrefixes ? $arrayMutatorPrefixes : self::$defaultArrayMutatorPrefixes; + + $this->arrayMutatorPrefixesFirst = array_merge($this->arrayMutatorPrefixes, array_diff($this->mutatorPrefixes, $this->arrayMutatorPrefixes)); + $this->arrayMutatorPrefixesLast = array_reverse($this->arrayMutatorPrefixesFirst); } /** @@ -330,7 +336,9 @@ private function getMutatorMethod($class, $property) $ucProperty = ucfirst($property); $ucSingulars = (array) Inflector::singularize($ucProperty); - foreach ($this->mutatorPrefixes as $prefix) { + $mutatorPrefixes = \in_array($ucProperty, $ucSingulars, true) ? $this->arrayMutatorPrefixesLast : $this->arrayMutatorPrefixesFirst; + + foreach ($mutatorPrefixes as $prefix) { $names = [$ucProperty]; if (\in_array($prefix, $this->arrayMutatorPrefixes)) { $names = array_merge($names, $ucSingulars); diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index 5a5c0c7b62c6a..36fc9d55e37f8 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -61,6 +61,7 @@ public function testGetProperties() 'realParent', 'xTotals', 'YT', + 'date', 'c', 'd', 'e', @@ -96,6 +97,7 @@ public function testGetPropertiesWithCustomPrefixes() 'foo4', 'foo5', 'files', + 'date', 'c', 'd', 'e', @@ -156,6 +158,8 @@ public function typesProvider() ['staticSetter', null], ['self', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy')]], ['realParent', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')]], + ['date', [new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class)]], + ['dates', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, \DateTime::class))]], ]; } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index 663fef84c7760..4a7b7c0951d46 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -190,4 +190,12 @@ public function getXTotals() public function getYT() { } + + public function setDate(\DateTime $date) + { + } + + public function addDate(\DateTime $date) + { + } } From 7f33f1fa3a0c0fab863b4e6b67e2de9a68384cf8 Mon Sep 17 00:00:00 2001 From: ampaze Date: Thu, 2 Apr 2020 13:53:10 +0200 Subject: [PATCH 09/51] Support for Content Security Policy style-src-elem and script-src-elem in WebProfiler If a `style-src-elem` or `script-src-elem` Content Security Policy exist, the WebProfiler Styles or Scripts will be rejected as the nonce is missing. --- .../WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php b/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php index a38e7c686fd0a..e62895fe6d2b2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Csp/ContentSecurityPolicyHandler.php @@ -128,7 +128,7 @@ private function updateCspHeaders(Response $response, array $nonces = []) $headers = $this->getCspHeaders($response); foreach ($headers as $header => $directives) { - foreach (['script-src' => 'csp_script_nonce', 'style-src' => 'csp_style_nonce'] as $type => $tokenName) { + foreach (['script-src' => 'csp_script_nonce', 'script-src-elem' => 'csp_script_nonce', 'style-src' => 'csp_style_nonce', 'style-src-elem' => 'csp_style_nonce'] as $type => $tokenName) { if ($this->authorizesInline($directives, $type)) { continue; } From 923c24f4383387778439c3e5d9112b7160721d27 Mon Sep 17 00:00:00 2001 From: rosier Date: Mon, 30 Mar 2020 19:57:25 +0200 Subject: [PATCH 10/51] No need to reconnect the bags to the session Bug https://bugs.php.net/70013 was fixed before the release of PHP v7.0 --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 5165b5d0d882f..d6ce2a79def98 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -223,10 +223,6 @@ public function regenerate($destroy = false, $lifetime = null) $isRegenerated = session_regenerate_id($destroy); - // The reference to $_SESSION in session bags is lost in PHP7 and we need to re-create it. - // @see https://bugs.php.net/70013 - $this->loadSession(); - if (null !== $this->emulateSameSite) { $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); if (null !== $originalCookie) { From d43ef4ec920ec570b395cb29de942c03deeced61 Mon Sep 17 00:00:00 2001 From: Serhiy Lunak Date: Sat, 28 Mar 2020 15:25:34 +0000 Subject: [PATCH 11/51] [Validator] Add missing Ukrainian and Russian translations --- .../Resources/translations/validators.ru.xlf | 12 ++++++++++++ .../Resources/translations/validators.uk.xlf | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index 80911a9902910..3c03fd8525cca 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -370,6 +370,18 @@ This value is not a valid hostname. Значение не является корректным именем хоста. + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Количество элементов в этой коллекции должно быть кратным {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Значение должно удовлетворять как минимум одному из следующих ограничений: + + + Each element of this collection should satisfy its own set of constraints. + Каждый элемент этой коллекции должен удовлетворять своему собственному набору ограничений. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf index cba61915544a3..688e11fbe929c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.uk.xlf @@ -366,6 +366,22 @@ This value should be between {{ min }} and {{ max }}. Значення має бути між {{ min }} та {{ max }}. + + This value is not a valid hostname. + Значення не є дійсним іменем хоста. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Кількість елементів у цій колекції повинна бути кратною {{ compared_value }}. + + + This value should satisfy at least one of the following constraints: + Значення повинно задовольняти хоча б одному з наступних обмежень: + + + Each element of this collection should satisfy its own set of constraints. + Кожен елемент цієї колекції повинен задовольняти власному набору обмежень. + From 1fafff7c10b11d6079c10d65b85272c586a20a4f Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Fri, 3 Apr 2020 12:40:07 +0200 Subject: [PATCH 12/51] [Serializer] Fix unitialized properties (from PHP 7.4.2) when serializing context for the cache key --- .../Normalizer/AbstractObjectNormalizer.php | 1 + .../AbstractObjectNormalizerTest.php | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 56dc3c590ede3..1eba26343dd1a 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -400,6 +400,7 @@ protected function createChildContext(array $parentContext, $attribute/*, string */ private function getCacheKey($format, array $context) { + unset($context[self::OBJECT_TO_POPULATE]); unset($context['cache_key']); // avoid artificially different keys try { return md5($format.serialize([ diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index d5d7cace362e4..d269da27e810d 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -163,6 +163,14 @@ public function testDenormalizeStringCollectionDecodedFromXmlWithTwoChildren() $this->assertEquals('bar', $stringCollection->children[1]); } + public function testDenormalizeNotSerializableObjectToPopulate() + { + $normalizer = new AbstractObjectNormalizerDummy(); + $normalizedData = $normalizer->denormalize(['foo' => 'foo'], Dummy::class, null, [AbstractObjectNormalizer::OBJECT_TO_POPULATE => new NotSerializable()]); + + $this->assertSame('foo', $normalizedData->foo); + } + private function getDenormalizerForStringCollection() { $extractor = $this->getMockBuilder(PhpDocExtractor::class)->getMock(); @@ -379,3 +387,15 @@ public function setSerializer(SerializerInterface $serializer) $this->serializer = $serializer; } } + +class NotSerializable +{ + public function __sleep() + { + if (class_exists(\Error::class)) { + throw new \Error('not serializable'); + } + + throw new \Exception('not serializable'); + } +} From 8a56c506e348bfb1aba42cdd713fae9dedfc2855 Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Tue, 31 Mar 2020 11:41:21 +0200 Subject: [PATCH 13/51] Allow URL-encoded special characters in basic auth part of URLs Resolves: https://github.com/symfony/symfony/issues/36285 --- src/Symfony/Component/Validator/Constraints/UrlValidator.php | 2 +- .../Validator/Tests/Constraints/UrlValidatorTest.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index d934162eeefc3..97a05450754ea 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -23,7 +23,7 @@ class UrlValidator extends ConstraintValidator { const PATTERN = '~^ (%s):// # protocol - (([\_\.\pL\pN-]+:)?([\_\.\pL\pN-]+)@)? # basic auth + (((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+)@)? # basic auth ( ([\pL\pN\pS\-\_\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name | # or diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php index 0357172680c61..6bcc5c54c5928 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php @@ -122,6 +122,8 @@ public function getValidUrls() ['http://user.name:pass.word@symfony.com'], ['http://user-name@symfony.com'], ['http://user_name@symfony.com'], + ['http://u%24er:password@symfony.com'], + ['http://user:pa%24%24word@symfony.com'], ['http://symfony.com?'], ['http://symfony.com?query=1'], ['http://symfony.com/?query=1'], @@ -168,6 +170,8 @@ public function getInvalidUrls() ['http://:password@@symfony.com'], ['http://username:passwordsymfony.com'], ['http://usern@me:password@symfony.com'], + ['http://nota%hex:password@symfony.com'], + ['http://username:nota%hex@symfony.com'], ['http://example.com/exploit.html?'], ['http://example.com/exploit.html?hel lo'], ['http://example.com/exploit.html?not_a%hex'], From 3e943435c98f71c828759f06fb42a6a6b692f003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 4 Apr 2020 09:51:57 +0200 Subject: [PATCH 14/51] [Serializer] Remove unused variable --- .../Serializer/Normalizer/AbstractObjectNormalizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 1eba26343dd1a..c1fc4ad82f93a 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -304,7 +304,7 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma */ protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, $parameterName, $parameterData, array $context, $format = null) { - if (null === $this->propertyTypeExtractor || null === $types = $this->propertyTypeExtractor->getTypes($class->getName(), $parameterName)) { + if (null === $this->propertyTypeExtractor || null === $this->propertyTypeExtractor->getTypes($class->getName(), $parameterName)) { return parent::denormalizeParameter($class, $parameter, $parameterName, $parameterData, $context, $format); } From 3e824de3855660264f1348f7502a3a9f148732cf Mon Sep 17 00:00:00 2001 From: Guite Date: Sun, 9 Feb 2020 17:51:23 +0100 Subject: [PATCH 15/51] [HttpFoundation] Fixed session migration with custom cookie lifetime --- .../Session/Storage/NativeSessionStorage.php | 8 +++++--- .../Session/Storage/NativeSessionStorageTest.php | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 7502897a4456b..66343cd31e4d6 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -152,7 +152,7 @@ public function start() // ok to try and start the session if (!session_start()) { - throw new \RuntimeException('Failed to start the session'); + throw new \RuntimeException('Failed to start the session.'); } if (null !== $this->emulateSameSite) { @@ -213,8 +213,10 @@ public function regenerate($destroy = false, $lifetime = null) return false; } - if (null !== $lifetime) { + if (null !== $lifetime && $lifetime != ini_get('session.cookie_lifetime')) { + $this->save(); ini_set('session.cookie_lifetime', $lifetime); + $this->start(); } if ($destroy) { @@ -314,7 +316,7 @@ public function registerBag(SessionBagInterface $bag) public function getBag($name) { if (!isset($this->bags[$name])) { - throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); + throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); } if (!$this->started && $this->saveHandler->isActive()) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index d2cf324525443..7cfcd223e0323 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -123,6 +123,19 @@ public function testRegenerateDestroy() $this->assertEquals(11, $storage->getBag('attributes')->get('legs')); } + public function testRegenerateWithCustomLifetime() + { + $storage = $this->getStorage(); + $storage->start(); + $id = $storage->getId(); + $lifetime = 999999; + $storage->getBag('attributes')->set('legs', 11); + $storage->regenerate(false, $lifetime); + $this->assertNotEquals($id, $storage->getId()); + $this->assertEquals(11, $storage->getBag('attributes')->get('legs')); + $this->assertEquals($lifetime, ini_get('session.cookie_lifetime')); + } + public function testSessionGlobalIsUpToDateAfterIdRegeneration() { $storage = $this->getStorage(); From 3c8bf2d29d5fa19d2ef9eaffec77cde358c525ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Masforn=C3=A9?= Date: Wed, 1 Apr 2020 23:52:46 +0200 Subject: [PATCH 16/51] [PropertyAccess] Improve message of unitialized property in php 7.4 --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 2 +- .../Component/PropertyAccess/Tests/PropertyAccessorTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 66b38eaf3caef..d1b3625fb1d66 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -505,7 +505,7 @@ private function readProperty($zval, $property) if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { $r = new \ReflectionProperty($matches[1], $matches[2]); - throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%3$s". You should either initialize it or make it nullable using "?%3$s" instead.', $r->getDeclaringClass()->getName(), $r->getName(), $r->getType()->getName()), 0, $e); + throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%2$s". You should initialize it or declare a default value instead.', $r->getDeclaringClass()->getName(), $r->getType()->getName()), 0, $e); } throw $e; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 62a95d68e9304..6ccf674113b86 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -126,7 +126,7 @@ public function testGetValueThrowsExceptionIfIndexNotFoundAndIndexExceptionsEnab public function testGetValueThrowsExceptionIfUninitializedProperty() { $this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException'); - $this->expectExceptionMessage('The property "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedProperty::$uninitialized" is not readable because it is typed "string". You should either initialize it or make it nullable using "?string" instead.'); + $this->expectExceptionMessage('The property "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedProperty::$uninitialized" is not readable because it is typed "string". You should initialize it or declare a default value instead.'); $this->propertyAccessor->getValue(new UninitializedProperty(), 'uninitialized'); } From 112b5de3cf35b651c137cce684bd52cff2b49152 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 6 Apr 2020 10:30:32 +0200 Subject: [PATCH 17/51] remove assertions that can never be reached --- .../Tests/Debug/OptionsResolverIntrospectorTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php b/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php index 8d6e9f63f6370..5fdb9e2657f3b 100644 --- a/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php +++ b/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php @@ -44,7 +44,7 @@ public function testGetDefaultThrowsOnNoConfiguredValue() $resolver->setDefined($option = 'foo'); $debug = new OptionsResolverIntrospector($resolver); - $this->assertSame('bar', $debug->getDefault($option)); + $debug->getDefault($option); } public function testGetDefaultThrowsOnNotDefinedOption() @@ -54,7 +54,7 @@ public function testGetDefaultThrowsOnNotDefinedOption() $resolver = new OptionsResolver(); $debug = new OptionsResolverIntrospector($resolver); - $this->assertSame('bar', $debug->getDefault('foo')); + $debug->getDefault('foo'); } public function testGetLazyClosures() @@ -75,7 +75,7 @@ public function testGetLazyClosuresThrowsOnNoConfiguredValue() $resolver->setDefined($option = 'foo'); $debug = new OptionsResolverIntrospector($resolver); - $this->assertSame('bar', $debug->getLazyClosures($option)); + $debug->getLazyClosures($option); } public function testGetLazyClosuresThrowsOnNotDefinedOption() @@ -85,7 +85,7 @@ public function testGetLazyClosuresThrowsOnNotDefinedOption() $resolver = new OptionsResolver(); $debug = new OptionsResolverIntrospector($resolver); - $this->assertSame('bar', $debug->getLazyClosures('foo')); + $debug->getLazyClosures('foo'); } public function testGetAllowedTypes() From a20110c6b602b6f2217ab0961069342572523012 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 6 Apr 2020 11:49:16 +0200 Subject: [PATCH 18/51] [WebProfilerBundle] fix test --- .../Tests/Csp/ContentSecurityPolicyHandlerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php index acccc7cbfb6d2..349db2aaf75b4 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Csp/ContentSecurityPolicyHandlerTest.php @@ -41,7 +41,7 @@ public function testOnKernelResponse($nonce, $expectedNonce, Request $request, R $this->assertFalse($response->headers->has('X-SymfonyProfiler-Style-Nonce')); foreach ($expectedCsp as $header => $value) { - $this->assertSame($value, $response->headers->get($header)); + $this->assertSame($value, $response->headers->get($header), $header); } } @@ -131,7 +131,7 @@ public function provideRequestAndResponsesForOnKernelResponse() ['csp_script_nonce' => $nonce, 'csp_style_nonce' => $nonce], $this->createRequest(), $this->createResponse(['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'']), - ['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; style-src \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; style-src \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null], + ['Content-Security-Policy' => 'default-src \'self\' domain.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src-elem \'self\' domain.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'Content-Security-Policy-Report-Only' => 'default-src \'self\' domain-report-only.com; script-src \'self\' \'unsafe-inline\'; script-src-elem \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'; style-src-elem \'self\' domain-report-only.com \'unsafe-inline\' \'nonce-'.$nonce.'\'', 'X-Content-Security-Policy' => null], ], [ $nonce, From 995ef18f957628202923d7873c583cfe835cc45d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 6 Apr 2020 12:01:14 +0200 Subject: [PATCH 19/51] [PropertyAccess] fix tests --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 4 ++-- .../Component/PropertyAccess/Tests/PropertyAccessorTest.php | 2 +- src/Symfony/Component/Yaml/Inline.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index d1b3625fb1d66..6f715d620418c 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -472,7 +472,7 @@ private function readProperty($zval, $property) } catch (\TypeError $e) { // handle uninitialized properties in PHP >= 7 if (preg_match((sprintf('/^Return value of %s::%s\(\) must be of the type (\w+), null returned$/', preg_quote(\get_class($object)), $access[self::ACCESS_NAME])), $e->getMessage(), $matches)) { - throw new AccessException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Have you forgotten to initialize a property or to make the return type nullable using "?%3$s" instead?', \get_class($object), $access[self::ACCESS_NAME], $matches[1]), 0, $e); + throw new AccessException(sprintf('The method "%s::%s()" returned "null", but expected type "%3$s". Did you forget to initialize a property or to make the return type nullable using "?%3$s"?', \get_class($object), $access[self::ACCESS_NAME], $matches[1]), 0, $e); } throw $e; @@ -505,7 +505,7 @@ private function readProperty($zval, $property) if (\PHP_VERSION_ID >= 70400 && preg_match('/^Typed property ([\w\\\]+)::\$(\w+) must not be accessed before initialization$/', $e->getMessage(), $matches)) { $r = new \ReflectionProperty($matches[1], $matches[2]); - throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%2$s". You should initialize it or declare a default value instead.', $r->getDeclaringClass()->getName(), $r->getType()->getName()), 0, $e); + throw new AccessException(sprintf('The property "%s::$%s" is not readable because it is typed "%s". You should initialize it or declare a default value instead.', $r->getDeclaringClass()->getName(), $r->getName(), $r->getType()->getName()), 0, $e); } throw $e; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 6ccf674113b86..d8331e76ad811 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -137,7 +137,7 @@ public function testGetValueThrowsExceptionIfUninitializedProperty() public function testGetValueThrowsExceptionIfUninitializedPropertyWithGetter() { $this->expectException('Symfony\Component\PropertyAccess\Exception\AccessException'); - $this->expectExceptionMessage('The method "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty::getUninitialized()" returned "null", but expected type "array". Have you forgotten to initialize a property or to make the return type nullable using "?array" instead?'); + $this->expectExceptionMessage('The method "Symfony\Component\PropertyAccess\Tests\Fixtures\UninitializedPrivateProperty::getUninitialized()" returned "null", but expected type "array". Did you forget to initialize a property or to make the return type nullable using "?array"?'); $this->propertyAccessor->getValue(new UninitializedPrivateProperty(), 'uninitialized'); } diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 7198d077980c2..4c7d37428e474 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -720,7 +720,7 @@ private static function evaluateScalar($scalar, $flags, $references = []) throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); + throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } return null; @@ -738,7 +738,7 @@ private static function evaluateScalar($scalar, $flags, $references = []) throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); + throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Did you forget to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber + 1, $scalar, self::$parsedFilename); } return null; From aebe8ae1632b363752808f80c3e72a76326769ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Tue, 7 Apr 2020 11:39:41 +0200 Subject: [PATCH 20/51] [Workflow] Use a strict comparison when retrieving raw markin in MarkingStore --- .../MarkingStore/SingleStateMarkingStore.php | 2 +- .../MarkingStore/SingleStateMarkingStoreTest.php | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php b/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php index daccc65b41606..cd102f4ce67a2 100644 --- a/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php +++ b/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php @@ -44,7 +44,7 @@ public function getMarking($subject) { $placeName = $this->propertyAccessor->getValue($subject, $this->property); - if (!$placeName) { + if (null === $placeName) { return new Marking(); } diff --git a/src/Symfony/Component/Workflow/Tests/MarkingStore/SingleStateMarkingStoreTest.php b/src/Symfony/Component/Workflow/Tests/MarkingStore/SingleStateMarkingStoreTest.php index 2e00714d2762a..0db37986cfc70 100644 --- a/src/Symfony/Component/Workflow/Tests/MarkingStore/SingleStateMarkingStoreTest.php +++ b/src/Symfony/Component/Workflow/Tests/MarkingStore/SingleStateMarkingStoreTest.php @@ -30,4 +30,17 @@ public function testGetSetMarking() $this->assertEquals($marking, $marking2); } + + public function testAlmostEmptyPlaceName() + { + $subject = new \stdClass(); + $subject->myMarks = 0; + + $markingStore = new SingleStateMarkingStore('myMarks'); + + $marking = $markingStore->getMarking($subject); + + $this->assertInstanceOf(Marking::class, $marking); + $this->assertCount(1, $marking->getPlaces()); + } } From 117ee34698e9bf2383d57aee6304b2c1fc7fab28 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Mon, 6 Apr 2020 21:16:17 +0200 Subject: [PATCH 21/51] [Validator] Fixed default group for nested composite constraints --- .../Validator/Constraints/Composite.php | 3 ++- .../Tests/Constraints/CollectionTest.php | 12 +++++++++ .../Constraints/CollectionValidatorTest.php | 23 ++++++++++++++++ .../Tests/Constraints/CompositeTest.php | 26 ++++++++++++++++++- 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/Composite.php b/src/Symfony/Component/Validator/Constraints/Composite.php index bd7030ee27a44..b14276c3bbf1a 100644 --- a/src/Symfony/Component/Validator/Constraints/Composite.php +++ b/src/Symfony/Component/Validator/Constraints/Composite.php @@ -88,7 +88,8 @@ public function __construct($options = null) } } - $this->groups = array_keys($mergedGroups); + // prevent empty composite constraint to have empty groups + $this->groups = array_keys($mergedGroups) ?: [self::DEFAULT_GROUP]; $this->$compositeOption = $nestedConstraints; return; diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php index fef129cfa7494..254154dae7244 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php @@ -100,4 +100,16 @@ public function testAcceptRequiredConstraintAsOneElementArray() $this->assertEquals($collection1, $collection2); } + + public function testConstraintHasDefaultGroupWithOptionalValues() + { + $constraint = new Collection([ + 'foo' => new Required(), + 'bar' => new Optional(), + ]); + + $this->assertEquals(['Default'], $constraint->groups); + $this->assertEquals(['Default'], $constraint->fields['foo']->groups); + $this->assertEquals(['Default'], $constraint->fields['bar']->groups); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php index e0ccdba754b0b..11913eb2307ac 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CollectionValidatorTest.php @@ -143,6 +143,29 @@ public function testExtraFieldsDisallowed() ->assertRaised(); } + public function testExtraFieldsDisallowedWithOptionalValues() + { + $constraint = new Optional(); + + $data = $this->prepareTestData([ + 'baz' => 6, + ]); + + $this->validator->validate($data, new Collection([ + 'fields' => [ + 'foo' => $constraint, + ], + 'extraFieldsMessage' => 'myMessage', + ])); + + $this->buildViolation('myMessage') + ->setParameter('{{ field }}', '"baz"') + ->atPath('property.path[baz]') + ->setInvalidValue(6) + ->setCode(Collection::NO_SUCH_FIELD_ERROR) + ->assertRaised(); + } + // bug fix public function testNullNotConsideredExtraField() { diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php index 2d42807821bb3..287fd6d6681cb 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CompositeTest.php @@ -19,7 +19,7 @@ class ConcreteComposite extends Composite { - public $constraints; + public $constraints = []; protected function getCompositeOption() { @@ -37,6 +37,30 @@ public function getDefaultOption() */ class CompositeTest extends TestCase { + public function testConstraintHasDefaultGroup() + { + $constraint = new ConcreteComposite([ + new NotNull(), + new NotBlank(), + ]); + + $this->assertEquals(['Default'], $constraint->groups); + $this->assertEquals(['Default'], $constraint->constraints[0]->groups); + $this->assertEquals(['Default'], $constraint->constraints[1]->groups); + } + + public function testNestedCompositeConstraintHasDefaultGroup() + { + $constraint = new ConcreteComposite([ + new ConcreteComposite(), + new ConcreteComposite(), + ]); + + $this->assertEquals(['Default'], $constraint->groups); + $this->assertEquals(['Default'], $constraint->constraints[0]->groups); + $this->assertEquals(['Default'], $constraint->constraints[1]->groups); + } + public function testMergeNestedGroupsIfNoExplicitParentGroup() { $constraint = new ConcreteComposite([ From 67f336b808ff5869cffbdf56333ced6cd54589ac Mon Sep 17 00:00:00 2001 From: Ivan Grigoriev Date: Tue, 4 Feb 2020 19:53:14 +0300 Subject: [PATCH 22/51] do not merge constraints within interfaces --- .../Factory/LazyLoadingMetadataFactory.php | 29 +++++++------------ .../Tests/Fixtures/AbstractPropertyGetter.php | 13 +++++++++ .../Tests/Fixtures/ChildGetterInterface.php | 7 +++++ .../Tests/Fixtures/PropertyGetter.php | 12 ++++++++ .../Fixtures/PropertyGetterInterface.php | 8 +++++ .../LazyLoadingMetadataFactoryTest.php | 25 +++++++++++++++- 6 files changed, 74 insertions(+), 20 deletions(-) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/AbstractPropertyGetter.php create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/ChildGetterInterface.php create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/PropertyGetter.php create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/PropertyGetterInterface.php diff --git a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php index 6bd16c1c7dcae..b17ff691fba48 100644 --- a/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php +++ b/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php @@ -117,34 +117,25 @@ public function getMetadataFor($value) private function mergeConstraints(ClassMetadata $metadata) { + if ($metadata->getReflectionClass()->isInterface()) { + return; + } + // Include constraints from the parent class if ($parent = $metadata->getReflectionClass()->getParentClass()) { $metadata->mergeConstraints($this->getMetadataFor($parent->name)); } - $interfaces = $metadata->getReflectionClass()->getInterfaces(); - - $interfaces = array_filter($interfaces, function ($interface) use ($parent, $interfaces) { - $interfaceName = $interface->getName(); - - if ($parent && $parent->implementsInterface($interfaceName)) { - return false; - } - - foreach ($interfaces as $i) { - if ($i !== $interface && $i->implementsInterface($interfaceName)) { - return false; - } - } - - return true; - }); - // Include constraints from all directly implemented interfaces - foreach ($interfaces as $interface) { + foreach ($metadata->getReflectionClass()->getInterfaces() as $interface) { if ('Symfony\Component\Validator\GroupSequenceProviderInterface' === $interface->name) { continue; } + + if ($parent && \in_array($interface->getName(), $parent->getInterfaceNames(), true)) { + continue; + } + $metadata->mergeConstraints($this->getMetadataFor($interface->name)); } } diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/AbstractPropertyGetter.php b/src/Symfony/Component/Validator/Tests/Fixtures/AbstractPropertyGetter.php new file mode 100644 index 0000000000000..3df0b9469ddf4 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/AbstractPropertyGetter.php @@ -0,0 +1,13 @@ +property; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/ChildGetterInterface.php b/src/Symfony/Component/Validator/Tests/Fixtures/ChildGetterInterface.php new file mode 100644 index 0000000000000..65c144bbeadb9 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/ChildGetterInterface.php @@ -0,0 +1,7 @@ + [ 'Default', 'EntityParentInterface', - 'EntityInterfaceB', 'Entity', ]]), ]; @@ -186,6 +188,15 @@ public function testGroupsFromParent() $this->assertContains('EntityStaticCar', $groups); $this->assertContains('EntityStaticVehicle', $groups); } + + public function testMultipathInterfaceConstraint() + { + $factory = new LazyLoadingMetadataFactory(new PropertyGetterInterfaceConstraintLoader()); + $metadata = $factory->getMetadataFor(PropertyGetter::class); + $constraints = $metadata->getPropertyMetadata('property'); + + $this->assertCount(1, $constraints); + } } class TestLoader implements LoaderInterface @@ -195,3 +206,15 @@ public function loadClassMetadata(ClassMetadata $metadata) $metadata->addConstraint(new ConstraintA()); } } + +class PropertyGetterInterfaceConstraintLoader implements LoaderInterface +{ + public function loadClassMetadata(ClassMetadata $metadata) + { + if (PropertyGetterInterface::class === $metadata->getClassName()) { + $metadata->addGetterConstraint('property', new NotBlank()); + } + + return true; + } +} From 728cd66a1317c159fb2c0722af548f9d2d8173d3 Mon Sep 17 00:00:00 2001 From: Artem Lopata Date: Fri, 10 Apr 2020 13:43:00 +0200 Subject: [PATCH 23/51] RepeatedType should always have inner types mapped --- .../Form/Extension/Core/Type/RepeatedType.php | 7 ++-- .../Extension/Core/Type/RepeatedTypeTest.php | 36 +++++++++++++++++++ .../Form/Tests/Fixtures/NotMappedType.php | 23 ++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/NotMappedType.php diff --git a/src/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php b/src/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php index ffb7520a582b6..6ed403523cb77 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/RepeatedType.php @@ -31,13 +31,16 @@ public function buildForm(FormBuilderInterface $builder, array $options) $options['options']['error_bubbling'] = $options['error_bubbling']; } + // children fields must always be mapped + $defaultOptions = ['mapped' => true]; + $builder ->addViewTransformer(new ValueToDuplicatesTransformer([ $options['first_name'], $options['second_name'], ])) - ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options'])) - ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options'])) + ->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options'], $defaultOptions)) + ->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options'], $defaultOptions)) ; } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php index 8b4666d6fa5f0..3d5544c05d25a 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Form; +use Symfony\Component\Form\Tests\Fixtures\NotMappedType; class RepeatedTypeTest extends BaseTypeTest { @@ -78,6 +79,41 @@ public function testSetRequired() $this->assertFalse($form['second']->isRequired()); } + public function testMappedOverridesDefault() + { + $form = $this->factory->create(NotMappedType::class); + $this->assertFalse($form->getConfig()->getMapped()); + + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'type' => NotMappedType::class, + ]); + + $this->assertTrue($form['first']->getConfig()->getMapped()); + $this->assertTrue($form['second']->getConfig()->getMapped()); + } + + /** + * @dataProvider notMappedConfigurationKeys + */ + public function testNotMappedInnerIsOverridden($configurationKey) + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'type' => TextTypeTest::TESTED_TYPE, + $configurationKey => ['mapped' => false], + ]); + + $this->assertTrue($form['first']->getConfig()->getMapped()); + $this->assertTrue($form['second']->getConfig()->getMapped()); + } + + public function notMappedConfigurationKeys() + { + return [ + ['first_options'], + ['second_options'], + ]; + } + public function testSetInvalidOptions() { $this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException'); diff --git a/src/Symfony/Component/Form/Tests/Fixtures/NotMappedType.php b/src/Symfony/Component/Form/Tests/Fixtures/NotMappedType.php new file mode 100644 index 0000000000000..14c340b8917af --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/NotMappedType.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class NotMappedType extends AbstractType +{ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('mapped', false); + } +} From 015d8d7e869b015e08080396d75ec9d177df6bdc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 10 Apr 2020 22:02:31 +0200 Subject: [PATCH 24/51] =?UTF-8?q?[DI]=20=C2=B5fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Component/DependencyInjection/Loader/YamlFileLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 5a011c04ddaaf..ca52ff36c0db6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -355,7 +355,7 @@ private function parseDefinition($id, $service, $file, array $defaults) if (isset($service['alias'])) { $this->container->setAlias($id, $alias = new Alias($service['alias'])); - if (\array_key_exists('public', $service)) { + if (isset($service['public'])) { $alias->setPublic($service['public']); } elseif (isset($defaults['public'])) { $alias->setPublic($defaults['public']); From 8920f183fbb6489f622d94f5637e82bb36fc12fa Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 10 Apr 2020 22:35:26 +0200 Subject: [PATCH 25/51] [appveyor] bump cache --- phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit b/phpunit index c89d2e400b602..fbce26d8edcca 100755 --- a/phpunit +++ b/phpunit @@ -1,7 +1,7 @@ #!/usr/bin/env php Date: Sat, 11 Apr 2020 20:54:18 +0200 Subject: [PATCH 26/51] [Form] Removed legacy check in `ValidationListener` --- .../Extension/Validator/EventListener/ValidationListener.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php b/src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php index 80c94dc66e4d0..e6cd81a4245f5 100644 --- a/src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php +++ b/src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php @@ -55,8 +55,7 @@ public function validateForm(FormEvent $event) foreach ($this->validator->validate($form) as $violation) { // Allow the "invalid" constraint to be put onto // non-synchronized forms - // ConstraintViolation::getConstraint() must not expect to provide a constraint as long as Symfony\Component\Validator\ExecutionContext exists (before 3.0) - $allowNonSynchronized = (null === $violation->getConstraint() || $violation->getConstraint() instanceof Form) && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode(); + $allowNonSynchronized = $violation->getConstraint() instanceof Form && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode(); $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); } From 5182253aa267a719533c42292b91607d4f6c3574 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 12 Apr 2020 00:02:39 +0200 Subject: [PATCH 27/51] [travis][appveyor] don't cache .phpunit --- .appveyor.yml | 1 - .travis.yml | 1 - phpunit | 2 -- 3 files changed, 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 188dfe78a2493..85892655405f5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -4,7 +4,6 @@ clone_folder: c:\projects\symfony cache: - composer.phar - - .phpunit -> phpunit init: - SET PATH=c:\php;%PATH% diff --git a/.travis.yml b/.travis.yml index 4251d2fa0247c..cb35dc95f5e97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,6 @@ matrix: cache: directories: - - .phpunit - php-$MIN_PHP - ~/php-ext diff --git a/phpunit b/phpunit index fbce26d8edcca..abce96135b50d 100755 --- a/phpunit +++ b/phpunit @@ -1,8 +1,6 @@ #!/usr/bin/env php Date: Sun, 12 Apr 2020 11:28:02 +0200 Subject: [PATCH 28/51] silence E_NOTICE triggered since PHP 7.4 --- src/Symfony/Component/HttpKernel/Log/Logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php index f490293a62e03..e05d8c32ec797 100644 --- a/src/Symfony/Component/HttpKernel/Log/Logger.php +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -77,7 +77,7 @@ public function log($level, $message, array $context = []) } $formatter = $this->formatter; - fwrite($this->handle, $formatter($level, $message, $context)); + @fwrite($this->handle, $formatter($level, $message, $context)); } /** From 966989a2b9fc4a9a301f964d2164f28e8fb15913 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 12 Apr 2020 11:36:17 +0200 Subject: [PATCH 29/51] Revert "[travis][appveyor] don't cache .phpunit" This reverts commit 5182253aa267a719533c42292b91607d4f6c3574. --- .appveyor.yml | 1 + .travis.yml | 1 + phpunit | 2 ++ 3 files changed, 4 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 85892655405f5..188dfe78a2493 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -4,6 +4,7 @@ clone_folder: c:\projects\symfony cache: - composer.phar + - .phpunit -> phpunit init: - SET PATH=c:\php;%PATH% diff --git a/.travis.yml b/.travis.yml index cb35dc95f5e97..4251d2fa0247c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ matrix: cache: directories: + - .phpunit - php-$MIN_PHP - ~/php-ext diff --git a/phpunit b/phpunit index abce96135b50d..fbce26d8edcca 100755 --- a/phpunit +++ b/phpunit @@ -1,6 +1,8 @@ #!/usr/bin/env php Date: Sun, 12 Apr 2020 11:58:27 +0200 Subject: [PATCH 30/51] =?UTF-8?q?[Routing]=20=C2=B5tweaks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php | 2 +- src/Symfony/Component/Routing/Loader/XmlFileLoader.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index 3920fc4bef9f6..65633ca075ba4 100644 --- a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -67,7 +67,7 @@ public function load($resource, $type = null) if (!$routeCollection instanceof RouteCollection) { $type = \is_object($routeCollection) ? \get_class($routeCollection) : \gettype($routeCollection); - throw new \LogicException(sprintf('The "%s"::%s method must return a RouteCollection: "%s" returned.', \get_class($loaderObject), $method, $type)); + throw new \LogicException(sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', \get_class($loaderObject), $method, $type)); } // make the service file tracked so that if it changes, the cache rebuilds diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index 29dfdb1665b56..a9a9d09e0866b 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -240,9 +240,9 @@ private function parseConfigs(\DOMElement $node, $path) if ($controller = $node->getAttribute('controller')) { if (isset($defaults['_controller'])) { - $name = $node->hasAttribute('id') ? sprintf('"%s"', $node->getAttribute('id')) : sprintf('the "%s" tag', $node->tagName); + $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); - throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for %s.', $path, $name)); + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name); } $defaults['_controller'] = $controller; From ad6f75e5c85ec9adebee716858a6c0f5feeab4b3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 12 Apr 2020 16:22:30 +0200 Subject: [PATCH 31/51] Tweak the code to avoid fabbot false positives --- .../Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php | 8 ++++---- .../Bridge/Doctrine/Security/User/EntityUserProvider.php | 2 +- .../Bundle/WebServerBundle/Command/ServerLogCommand.php | 2 +- .../Asset/VersionStrategy/JsonManifestVersionStrategy.php | 2 +- src/Symfony/Component/Cache/Traits/MemcachedTrait.php | 2 +- src/Symfony/Component/Config/Definition/BaseNode.php | 2 +- .../Compiler/AbstractRecursivePass.php | 2 +- .../DependencyInjection/Loader/YamlFileLoader.php | 2 +- src/Symfony/Component/Filesystem/Filesystem.php | 8 ++++---- src/Symfony/Component/Form/Form.php | 8 ++++---- .../HttpKernel/Controller/ControllerResolver.php | 2 +- .../Intl/Data/Bundle/Reader/JsonBundleReader.php | 2 +- src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php | 8 ++++---- src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php | 4 ++-- .../Component/Ldap/Adapter/ExtLdap/EntryManager.php | 8 ++++---- src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php | 2 +- src/Symfony/Component/Process/Pipes/WindowsPipes.php | 2 +- .../Component/Security/Core/Encoder/EncoderFactory.php | 4 ++-- src/Symfony/Component/Serializer/Encoder/XmlEncoder.php | 2 +- src/Symfony/Component/Serializer/Serializer.php | 2 +- .../Component/Translation/Loader/JsonFileLoader.php | 2 +- .../Component/Translation/Loader/XliffFileLoader.php | 4 ++-- .../Validator/Constraints/AbstractComparisonValidator.php | 2 +- .../Component/Validator/Constraints/CallbackValidator.php | 2 +- 24 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php index fc60d12d7b395..7d824100b76bf 100644 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php +++ b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php @@ -96,7 +96,7 @@ public function destroy($sessionId) $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $stmt->execute(); } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to delete a session: %s.', $e->getMessage()), 0, $e); + throw new \RuntimeException('Exception was thrown when trying to delete a session: '.$e->getMessage(), 0, $e); } return true; @@ -115,7 +115,7 @@ public function gc($maxlifetime) $stmt->bindValue(':time', time() - $maxlifetime, \PDO::PARAM_INT); $stmt->execute(); } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to delete expired sessions: %s.', $e->getMessage()), 0, $e); + throw new \RuntimeException('Exception was thrown when trying to delete expired sessions: '.$e->getMessage(), 0, $e); } return true; @@ -142,7 +142,7 @@ public function read($sessionId) return ''; } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to read the session data: %s.', $e->getMessage()), 0, $e); + throw new \RuntimeException('Exception was thrown when trying to read the session data: '.$e->getMessage(), 0, $e); } } @@ -212,7 +212,7 @@ public function write($sessionId, $data) } } } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to write the session data: %s.', $e->getMessage()), 0, $e); + throw new \RuntimeException('Exception was thrown when trying to write the session data: '.$e->getMessage(), 0, $e); } return true; diff --git a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php index 1fe8a5c53a5ab..818c44a3da2af 100644 --- a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php @@ -92,7 +92,7 @@ public function refreshUser(UserInterface $user) $refreshedUser = $repository->find($id); if (null === $refreshedUser) { - throw new UsernameNotFoundException(sprintf('User with id %s not found.', json_encode($id))); + throw new UsernameNotFoundException('User with id '.json_encode($id).' not found.')); } } diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php index 5c9ce910ddf54..75d94321f4f0b 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php @@ -99,7 +99,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } if (!$socket = stream_socket_server($host, $errno, $errstr)) { - throw new RuntimeException(sprintf('Server start failed on "%s": %s %s.', $host, $errstr, $errno)); + throw new RuntimeException(sprintf('Server start failed on "%s": '.$errstr.' '.$errno, $host)); } foreach ($this->getLogs($socket) as $clientId => $message) { diff --git a/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php b/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php index 2ab686a561956..d052317678c80 100644 --- a/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php +++ b/src/Symfony/Component/Asset/VersionStrategy/JsonManifestVersionStrategy.php @@ -59,7 +59,7 @@ private function getManifestPath($path) $this->manifestData = json_decode(file_get_contents($this->manifestPath), true); if (0 < json_last_error()) { - throw new \RuntimeException(sprintf('Error parsing JSON from asset manifest file "%s" - %s.', $this->manifestPath, json_last_error_msg())); + throw new \RuntimeException(sprintf('Error parsing JSON from asset manifest file "%s": '.json_last_error_msg(), $this->manifestPath)); } } diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 3f4fb5243d0e2..3ff28d25b3576 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -272,7 +272,7 @@ private function checkResultCode($result) return $result; } - throw new CacheException(sprintf('MemcachedAdapter client error: %s.', strtolower($this->client->getResultMessage()))); + throw new CacheException('MemcachedAdapter client error: '.strtolower($this->client->getResultMessage())); } /** diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index bf57a9fa17bc5..1f6ef7f834b8c 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -335,7 +335,7 @@ final public function finalize($value) } catch (Exception $e) { throw $e; } catch (\Exception $e) { - throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": %s.', $this->getPath(), $e->getMessage()), $e->getCode(), $e); + throw new InvalidConfigurationException(sprintf('Invalid configuration for path "%s": '.$e->getMessage(), $this->getPath()), $e->getCode(), $e); } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php index 5ca2b2246b76b..27969e7067254 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -126,7 +126,7 @@ protected function getConstructor(Definition $definition, $required) throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); } } catch (\ReflectionException $e) { - throw new RuntimeException(sprintf('Invalid service "%s": %s.', $this->currentId, lcfirst(rtrim($e->getMessage(), '.')))); + throw new RuntimeException(sprintf('Invalid service "%s": '.lcfirst($e->getMessage()), $this->currentId)); } if (!$r = $r->getConstructor()) { if ($required) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index ca52ff36c0db6..bc0c55e94df41 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -660,7 +660,7 @@ protected function loadFile($file) try { $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); } catch (ParseException $e) { - throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: %s.', $file, $e->getMessage()), 0, $e); + throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: '.$e->getMessage(), $file), 0, $e); } finally { restore_error_handler(); } diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index f3d1fe44622a1..a8701533cbd38 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -101,7 +101,7 @@ public function mkdir($dirs, $mode = 0777) if (!is_dir($dir)) { // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one if (self::$lastError) { - throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir); + throw new IOException(sprintf('Failed to create "%s": '.self::$lastError, $dir), 0, null, $dir); } throw new IOException(sprintf('Failed to create "%s".', $dir), 0, null, $dir); } @@ -171,16 +171,16 @@ public function remove($files) if (is_link($file)) { // See https://bugs.php.net/52176 if (!(self::box('unlink', $file) || '\\' !== \DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError)); + throw new IOException(sprintf('Failed to remove symlink "%s": '.self::$lastError, $file)); } } elseif (is_dir($file)) { $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS)); if (!self::box('rmdir', $file) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError)); + throw new IOException(sprintf('Failed to remove directory "%s": '.self::$lastError, $file)); } } elseif (!self::box('unlink', $file) && file_exists($file)) { - throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError)); + throw new IOException(sprintf('Failed to remove file "%s": '.self::$lastError, $file)); } } } diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 53ac447d3d8bd..e9190b82b8466 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -1031,7 +1031,7 @@ private function modelToNorm($value) $value = $transformer->transform($value); } } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to transform data for property path "%s": %s', $this->getPropertyPath(), $exception->getMessage()), $exception->getCode(), $exception); + throw new TransformationFailedException(sprintf('Unable to transform data for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception); } return $value; @@ -1055,7 +1055,7 @@ private function normToModel($value) $value = $transformers[$i]->reverseTransform($value); } } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": %s', $this->getPropertyPath(), $exception->getMessage()), $exception->getCode(), $exception); + throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception); } return $value; @@ -1086,7 +1086,7 @@ private function normToView($value) $value = $transformer->transform($value); } } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to transform value for property path "%s": %s', $this->getPropertyPath(), $exception->getMessage()), $exception->getCode(), $exception); + throw new TransformationFailedException(sprintf('Unable to transform value for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception); } return $value; @@ -1112,7 +1112,7 @@ private function viewToNorm($value) $value = $transformers[$i]->reverseTransform($value); } } catch (TransformationFailedException $exception) { - throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": %s', $this->getPropertyPath(), $exception->getMessage()), $exception->getCode(), $exception); + throw new TransformationFailedException(sprintf('Unable to reverse value for property path "%s": '.$exception->getMessage(), $this->getPropertyPath()), $exception->getCode(), $exception); } return $value; diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 4e11ac640bd90..6244fdb9e5eaa 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -88,7 +88,7 @@ public function getController(Request $request) try { $callable = $this->createController($controller); } catch (\InvalidArgumentException $e) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s.', $request->getPathInfo(), $e->getMessage()), 0, $e); + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: '.$e->getMessage(), $request->getPathInfo()), 0, $e); } return $callable; diff --git a/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php b/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php index a56fd6af1c233..555dd377c9341 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php @@ -46,7 +46,7 @@ public function read($path, $locale) $data = json_decode(file_get_contents($fileName), true); if (null === $data) { - throw new RuntimeException(sprintf('The resource bundle "%s" contains invalid JSON: %s.', $fileName, json_last_error_msg())); + throw new RuntimeException(sprintf('The resource bundle "%s" contains invalid JSON: '.json_last_error_msg(), $fileName)); } return $data; diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php index fade430753dcc..f166c3dd3fb9c 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Collection.php @@ -48,7 +48,7 @@ public function count() return $count; } - throw new LdapException(sprintf('Error while retrieving entry count: %s.', ldap_error($this->connection->getResource()))); + throw new LdapException('Error while retrieving entry count: '.ldap_error($this->connection->getResource())); } public function getIterator() @@ -62,7 +62,7 @@ public function getIterator() } if (false === $current) { - throw new LdapException(sprintf('Could not rewind entries array: %s.', ldap_error($con))); + throw new LdapException('Could not rewind entries array: '.ldap_error($con)); } yield $this->getSingleEntry($con, $current); @@ -105,7 +105,7 @@ private function getSingleEntry($con, $current) $attributes = ldap_get_attributes($con, $current); if (false === $attributes) { - throw new LdapException(sprintf('Could not fetch attributes: %s.', ldap_error($con))); + throw new LdapException('Could not fetch attributes: '.ldap_error($con)); } $attributes = $this->cleanupAttributes($attributes); @@ -113,7 +113,7 @@ private function getSingleEntry($con, $current) $dn = ldap_get_dn($con, $current); if (false === $dn) { - throw new LdapException(sprintf('Could not fetch DN: %s.', ldap_error($con))); + throw new LdapException('Could not fetch DN: '.ldap_error($con)); } return new Entry($dn, $attributes); diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php index 2dcb215b921a4..9e988a8e6c87f 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php @@ -138,11 +138,11 @@ private function connect() } if (false === $this->connection) { - throw new LdapException(sprintf('Could not connect to Ldap server: %s.', ldap_error($this->connection))); + throw new LdapException('Could not connect to Ldap server: '.ldap_error($this->connection)); } if ('tls' === $this->config['encryption'] && false === @ldap_start_tls($this->connection)) { - throw new LdapException(sprintf('Could not initiate TLS connection: %s.', ldap_error($this->connection))); + throw new LdapException('Could not initiate TLS connection: '.ldap_error($this->connection)); } } diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php index 871c4b049562d..789672e7b22ef 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php @@ -38,7 +38,7 @@ public function add(Entry $entry) $con = $this->getConnectionResource(); if (!@ldap_add($con, $entry->getDn(), $entry->getAttributes())) { - throw new LdapException(sprintf('Could not add entry "%s": %s.', $entry->getDn(), ldap_error($con))); + throw new LdapException(sprintf('Could not add entry "%s": '.ldap_error($con), $entry->getDn())); } return $this; @@ -52,7 +52,7 @@ public function update(Entry $entry) $con = $this->getConnectionResource(); if (!@ldap_modify($con, $entry->getDn(), $entry->getAttributes())) { - throw new LdapException(sprintf('Could not update entry "%s": %s.', $entry->getDn(), ldap_error($con))); + throw new LdapException(sprintf('Could not update entry "%s": '.ldap_error($con), $entry->getDn())); } } @@ -64,7 +64,7 @@ public function remove(Entry $entry) $con = $this->getConnectionResource(); if (!@ldap_delete($con, $entry->getDn())) { - throw new LdapException(sprintf('Could not remove entry "%s": %s.', $entry->getDn(), ldap_error($con))); + throw new LdapException(sprintf('Could not remove entry "%s": '.ldap_error($con), $entry->getDn())); } } @@ -76,7 +76,7 @@ public function rename(Entry $entry, $newRdn, $removeOldRdn = true) $con = $this->getConnectionResource(); if (!@ldap_rename($con, $entry->getDn(), $newRdn, null, $removeOldRdn)) { - throw new LdapException(sprintf('Could not rename entry "%s" to "%s": %s.', $entry->getDn(), $newRdn, ldap_error($con))); + throw new LdapException(sprintf('Could not rename entry "%s" to "%s": '.ldap_error($con), $entry->getDn(), $newRdn)); } } diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php index 33742039fb32b..a5c049b166125 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Query.php @@ -45,7 +45,7 @@ public function __destruct() $this->search = null; if (!$success) { - throw new LdapException(sprintf('Could not free results: %s.', ldap_error($con))); + throw new LdapException('Could not free results: '.ldap_error($con)); } } diff --git a/src/Symfony/Component/Process/Pipes/WindowsPipes.php b/src/Symfony/Component/Process/Pipes/WindowsPipes.php index 44056d54cf65d..302b0509a86b7 100644 --- a/src/Symfony/Component/Process/Pipes/WindowsPipes.php +++ b/src/Symfony/Component/Process/Pipes/WindowsPipes.php @@ -57,7 +57,7 @@ public function __construct($input, $haveReadSupport) if (!$h = fopen($file.'.lock', 'w')) { restore_error_handler(); - throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s.', $lastError)); + throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError); } if (!flock($h, LOCK_EX | LOCK_NB)) { continue 2; diff --git a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php index f79eed1961fd5..feee0fe856a6d 100644 --- a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php +++ b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php @@ -71,10 +71,10 @@ private function createEncoder(array $config) $config = $this->getEncoderConfigFromAlgorithm($config); } if (!isset($config['class'])) { - throw new \InvalidArgumentException(sprintf('"class" must be set in %s.', json_encode($config))); + throw new \InvalidArgumentException('"class" must be set in '.json_encode($config)); } if (!isset($config['arguments'])) { - throw new \InvalidArgumentException(sprintf('"arguments" must be set in %s.', json_encode($config))); + throw new \InvalidArgumentException('"arguments" must be set in '.json_encode($config)); } $reflection = new \ReflectionClass($config['class']); diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index d7551183ddff2..dc932222e953e 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -431,7 +431,7 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) return $this->appendNode($parentNode, $data, 'data'); } - throw new NotEncodableValueException(sprintf('An unexpected value could not be serialized: %s.', !\is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data)))); + throw new NotEncodableValueException('An unexpected value could not be serialized: '.(!\is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data)))); } /** diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 1c125bc935df4..87b32a6ca5ba4 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -164,7 +164,7 @@ public function normalize($data, $format = null, array $context = []) throw new NotNormalizableValueException(sprintf('Could not normalize object of type "%s", no supporting normalizer found.', \get_class($data))); } - throw new NotNormalizableValueException(sprintf('An unexpected value could not be normalized: %s.', !\is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data)))); + throw new NotNormalizableValueException('An unexpected value could not be normalized: '.(!\is_resource($data) ? var_export($data, true) : sprintf('%s resource', get_resource_type($data)))); } /** diff --git a/src/Symfony/Component/Translation/Loader/JsonFileLoader.php b/src/Symfony/Component/Translation/Loader/JsonFileLoader.php index 5ab2e989e7a76..a02732e8d8f40 100644 --- a/src/Symfony/Component/Translation/Loader/JsonFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/JsonFileLoader.php @@ -30,7 +30,7 @@ protected function loadResource($resource) $messages = json_decode($data, true); if (0 < $errorCode = json_last_error()) { - throw new InvalidResourceException(sprintf('Error parsing JSON - %s.', $this->getJSONErrorMessage($errorCode))); + throw new InvalidResourceException('Error parsing JSON: '.$this->getJSONErrorMessage($errorCode)); } } diff --git a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php index b5333f1e4e36b..d09f434985107 100644 --- a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php @@ -53,7 +53,7 @@ private function extract($resource, MessageCatalogue $catalogue, $domain) try { $dom = XmlUtils::loadFile($resource); } catch (\InvalidArgumentException $e) { - throw new InvalidResourceException(sprintf('Unable to load "%s": %s.', $resource, $e->getMessage()), $e->getCode(), $e); + throw new InvalidResourceException(sprintf('Unable to load "%s": '.$e->getMessage(), $resource), $e->getCode(), $e); } $xliffVersion = $this->getVersionNumber($dom); @@ -194,7 +194,7 @@ private function validateSchema($file, \DOMDocument $dom, $schema) if (!@$dom->schemaValidateSource($schema)) { libxml_disable_entity_loader($disableEntities); - throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: %s.', $file, implode("\n", $this->getXmlErrors($internalErrors)))); + throw new InvalidResourceException(sprintf('Invalid resource provided: "%s"; Errors: '.implode("\n", $this->getXmlErrors($internalErrors)), $file)); } libxml_disable_entity_loader($disableEntities); diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php index c0840845480dd..10db1586155f6 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php @@ -55,7 +55,7 @@ public function validate($value, Constraint $constraint) try { $comparedValue = $this->getPropertyAccessor()->getValue($object, $path); } catch (NoSuchPropertyException $e) { - throw new ConstraintDefinitionException(sprintf('Invalid property path "%s" provided to "%s" constraint: %s.', $path, \get_class($constraint), $e->getMessage()), 0, $e); + throw new ConstraintDefinitionException(sprintf('Invalid property path "%s" provided to "%s" constraint: '.$e->getMessage(), $path, \get_class($constraint)), 0, $e); } } else { $comparedValue = $constraint->value; diff --git a/src/Symfony/Component/Validator/Constraints/CallbackValidator.php b/src/Symfony/Component/Validator/Constraints/CallbackValidator.php index 84f2c3295ceae..3accd2f9d6158 100644 --- a/src/Symfony/Component/Validator/Constraints/CallbackValidator.php +++ b/src/Symfony/Component/Validator/Constraints/CallbackValidator.php @@ -40,7 +40,7 @@ public function validate($object, Constraint $constraint) if (isset($method[0]) && \is_object($method[0])) { $method[0] = \get_class($method[0]); } - throw new ConstraintDefinitionException(sprintf('%s targeted by Callback constraint is not a valid callable.', json_encode($method))); + throw new ConstraintDefinitionException(json_encode($method).' targeted by Callback constraint is not a valid callable.'); } \call_user_func($method, $object, $this->context, $constraint->payload); From e4d4428bb3084c7a60fae6d1850983492b80e165 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 12 Apr 2020 18:39:58 +0200 Subject: [PATCH 32/51] Fix code --- .../Bridge/Doctrine/Security/User/EntityUserProvider.php | 2 +- .../Tests/Controller/ContainerControllerResolverTest.php | 2 +- .../Tests/Controller/ControllerResolverTest.php | 8 ++++---- .../Translation/Tests/Loader/JsonFileLoaderTest.php | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php index 818c44a3da2af..180341012fd1c 100644 --- a/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/User/EntityUserProvider.php @@ -92,7 +92,7 @@ public function refreshUser(UserInterface $user) $refreshedUser = $repository->find($id); if (null === $refreshedUser) { - throw new UsernameNotFoundException('User with id '.json_encode($id).' not found.')); + throw new UsernameNotFoundException('User with id '.json_encode($id).' not found.'); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php index b03169de93400..4c4abf5aa4d42 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php @@ -248,7 +248,7 @@ public function getUndefinedControllers() [ 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar', \InvalidArgumentException::class, - '/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/', + '/.?[cC]ontroller(.*?) for URI "\/" is not callable:( Expected method(.*) Available methods)?/', ], ]; } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index e34427a32e5c4..d2684791fecb4 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -131,10 +131,10 @@ public function getUndefinedControllers() ['foo', 'InvalidArgumentException', 'Unable to find controller "foo".'], ['oof::bar', 'InvalidArgumentException', 'Class "oof" does not exist.'], ['stdClass', 'InvalidArgumentException', 'Unable to find controller "stdClass".'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::staticsAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::privateAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::protectedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], - ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::undefinedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::staticsAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable: Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::privateAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable: Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::protectedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable: Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::undefinedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable: Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], ]; } diff --git a/src/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php b/src/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php index d264bb16b29d9..c5a9ca64d4d7f 100644 --- a/src/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php +++ b/src/Symfony/Component/Translation/Tests/Loader/JsonFileLoaderTest.php @@ -50,7 +50,7 @@ public function testLoadNonExistingResource() public function testParseException() { $this->expectException('Symfony\Component\Translation\Exception\InvalidResourceException'); - $this->expectExceptionMessage('Error parsing JSON - Syntax error, malformed JSON'); + $this->expectExceptionMessage('Error parsing JSON: Syntax error, malformed JSON'); $loader = new JsonFileLoader(); $resource = __DIR__.'/../fixtures/malformed.json'; $loader->load($resource, 'en', 'domain1'); From 311a944a0809b6a02e89815a76e8ef13a8f6c9ab Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 12 Apr 2020 18:54:01 +0200 Subject: [PATCH 33/51] Fix test --- src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php index d130803d44cae..b63e0c224fde8 100644 --- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php +++ b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php @@ -24,7 +24,7 @@ class LockHandlerTest extends TestCase public function testConstructWhenRepositoryDoesNotExist() { $this->expectException('Symfony\Component\Filesystem\Exception\IOException'); - $this->expectExceptionMessage('Failed to create "/a/b/c/d/e": mkdir(): Permission denied.'); + $this->expectExceptionMessage('Failed to create "/a/b/c/d/e": mkdir(): Permission denied'); if (!getenv('USER') || 'root' === getenv('USER')) { $this->markTestSkipped('This test will fail if run under superuser'); } From 51e0d3792caa7c53860b2c54bf2c949ddae8c7cd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 13 Apr 2020 11:14:49 +0200 Subject: [PATCH 34/51] [DI] fix loading defaults when using the PHP-DSL --- .../Compiler/CacheCollectorPass.php | 4 +++- .../Loader/Configurator/PrototypeConfigurator.php | 7 +++++-- .../Loader/Configurator/ServicesConfigurator.php | 12 +++++++++--- .../Tests/Fixtures/config/basic.expected.yml | 1 - .../Tests/Fixtures/config/child.expected.yml | 5 +---- .../Tests/Fixtures/config/defaults.expected.yml | 1 - .../Tests/Fixtures/config/instanceof.expected.yml | 2 -- .../Tests/Fixtures/config/php7.expected.yml | 1 - .../Tests/Fixtures/config/prototype.expected.yml | 2 -- .../Tests/Fixtures/config/services9.php | 3 +-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php index 7f8494d98e0ad..6bb614489eeb8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php @@ -44,7 +44,9 @@ public function process(ContainerBuilder $container) $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class); $recorder->setTags($definition->getTags()); - $recorder->setPublic($definition->isPublic()); + if (!$definition->isPublic() || !$definition->isPrivate()) { + $recorder->setPublic($definition->isPublic()); + } $recorder->setArguments([new Reference($innerId = $id.'.recorder_inner')]); $definition->setTags([]); diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php index d80c8b13389f2..3d844798d431a 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php @@ -45,10 +45,13 @@ class PrototypeConfigurator extends AbstractServiceConfigurator public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, $namespace, $resource, $allowParent) { $definition = new Definition(); - $definition->setPublic($defaults->isPublic()); + if (!$defaults->isPublic() || !$defaults->isPrivate()) { + $definition->setPublic($defaults->isPublic()); + } $definition->setAutowired($defaults->isAutowired()); $definition->setAutoconfigured($defaults->isAutoconfigured()); - $definition->setBindings($defaults->getBindings()); + // deep clone, to avoid multiple process of the same instance in the passes + $definition->setBindings(unserialize(serialize($defaults->getBindings()))); $definition->setChanges([]); $this->loader = $loader; diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php index e7677eb5e6dc6..b6ccbc63b4e81 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php @@ -79,10 +79,13 @@ final public function set($id, $class = null) $allowParent = !$defaults->getChanges() && empty($this->instanceof); $definition = new Definition(); - $definition->setPublic($defaults->isPublic()); + if (!$defaults->isPublic() || !$defaults->isPrivate()) { + $definition->setPublic($defaults->isPublic() && !$defaults->isPrivate()); + } $definition->setAutowired($defaults->isAutowired()); $definition->setAutoconfigured($defaults->isAutoconfigured()); - $definition->setBindings($defaults->getBindings()); + // deep clone, to avoid multiple process of the same instance in the passes + $definition->setBindings(unserialize(serialize($defaults->getBindings()))); $definition->setChanges([]); $configurator = new ServiceConfigurator($this->container, $this->instanceof, $allowParent, $this, $definition, $id, $defaults->getTags()); @@ -101,7 +104,10 @@ final public function set($id, $class = null) final public function alias($id, $referencedId) { $ref = static::processValue($referencedId, true); - $alias = new Alias((string) $ref, $this->defaults->isPublic()); + $alias = new Alias((string) $ref); + if (!$this->defaults->isPublic() || !$this->defaults->isPrivate()) { + $alias->setPublic($this->defaults->isPublic()); + } $this->container->setAlias($id, $alias); return new AliasConfigurator($this, $alias); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml index 1137961ade139..39a3b631b97eb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml @@ -6,5 +6,4 @@ services: synthetic: true App\BarService: class: App\BarService - public: true arguments: [!service { class: FooClass }] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml index aaab7131c4697..f60d6bb5b72e2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml @@ -6,10 +6,7 @@ services: synthetic: true foo: class: Class2 - public: true file: file.php lazy: true arguments: [!service { class: Class1, public: false }] - bar: - alias: foo - public: true + bar: '@foo' diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml index a534f7267a078..3f01b1099f73a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml @@ -6,7 +6,6 @@ services: synthetic: true App\BarService: class: App\BarService - public: true arguments: [!service { class: FooClass }] Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml index b12a304221dd8..1238a7bda4fbf 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml @@ -6,7 +6,6 @@ services: synthetic: true Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo - public: true tags: - { name: tag, k: v } lazy: true @@ -18,4 +17,3 @@ services: configurator: c foo: class: App\FooService - public: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml index 7c5b714ffbd7e..7cec320b2eec7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml @@ -13,7 +13,6 @@ services: arguments: ['@bar'] bar: class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo - public: true calls: - [setFoo, { }] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml index ebfe087d779cf..24a79401531c9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml @@ -6,7 +6,6 @@ services: synthetic: true Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo - public: true tags: - { name: foo } - { name: baz } @@ -15,7 +14,6 @@ services: factory: f Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar: class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar - public: true tags: - { name: foo } - { name: baz } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php index d9373a2a6f9e6..ef390937687b1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php @@ -14,7 +14,7 @@ $p->set('foo_class', FooClass::class) ->set('foo', 'bar'); - $s = $c->services(); + $s = $c->services()->defaults()->public(); $s->set('foo') ->args(['foo', ref('foo.baz'), ['%foo%' => 'foo is %foo%', 'foobar' => '%foo%'], true, ref('service_container')]) ->class(FooClass::class) @@ -120,7 +120,6 @@ ->tag('foo'); $s->set('tagged_iterator', 'Bar') - ->public() ->args([tagged('foo')]); $s->alias('alias_for_foo', 'foo')->private()->public(); From 15a8610c0c4aa69a13c6a3d25a604e27ed69abb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 15 Apr 2020 20:00:38 +0200 Subject: [PATCH 35/51] [Cache] Avoid memory leak in TraceableAdapter::reset() --- .../Component/Cache/Adapter/TraceableAdapter.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php index 4aed2d7181f83..cc855c132a83c 100644 --- a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php @@ -191,15 +191,11 @@ public function prune() */ public function reset() { - if (!$this->pool instanceof ResettableInterface) { - return; - } - $event = $this->start(__FUNCTION__); - try { + if ($this->pool instanceof ResettableInterface) { $this->pool->reset(); - } finally { - $event->end = microtime(true); } + + $this->clearCalls(); } public function getCalls() From dfb61c204c3d2149e36bcce7a9aefd020ff2f0c2 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Fri, 3 Apr 2020 17:40:36 +0200 Subject: [PATCH 36/51] [Form] Fixed handling groups sequence validation --- .../Validator/Constraints/FormValidator.php | 79 ++++++++++++++----- .../Form/Resources/config/validation.xml | 2 +- .../Constraints/FormValidatorTest.php | 39 ++++++++- .../Type/FormTypeValidatorExtensionTest.php | 65 ++++++++++++++- .../Validator/ValidatorExtensionTest.php | 56 ++++++++++++- 5 files changed, 212 insertions(+), 29 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 07ecabdad1346..14158f4c1cf74 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -24,6 +24,8 @@ */ class FormValidator extends ConstraintValidator { + private $resolvedGroups; + /** * {@inheritdoc} */ @@ -44,42 +46,68 @@ public function validate($form, Constraint $formConstraint) if ($form->isSubmitted() && $form->isSynchronized()) { // Validate the form data only if transformation succeeded - $groups = self::getValidationGroups($form); + $groups = $this->getValidationGroups($form); if (!$groups) { return; } $data = $form->getData(); - // Validate the data against its own constraints - if ($form->isRoot() && (\is_object($data) || \is_array($data))) { - if (($groups && \is_array($groups)) || ($groups instanceof GroupSequence && $groups->groups)) { - $validator->atPath('data')->validate($form->getData(), null, $groups); - } - } + $validateDataGraph = $form->isRoot() + && (\is_object($data) || \is_array($data)) + && (($groups && \is_array($groups)) || ($groups instanceof GroupSequence && $groups->groups)) + ; - // Validate the data against the constraints defined - // in the form + // Validate the data against the constraints defined in the form + /** @var Constraint[] $constraints */ $constraints = $config->getOption('constraints', []); if ($groups instanceof GroupSequence) { - $validator->atPath('data')->validate($form->getData(), $constraints, $groups); - // Otherwise validate a constraint only once for the first - // matching group - foreach ($groups as $group) { - if (\in_array($group, $formConstraint->groups)) { - $validator->atPath('data')->validate($form->getData(), $formConstraint, $group); - if (\count($this->context->getViolations()) > 0) { - break; + // Validate the data, the form AND nested fields in sequence + $violationsCount = $this->context->getViolations()->count(); + $fieldPropertyPath = \is_object($data) ? 'children[%s]' : 'children%s'; + $hasChildren = $form->count() > 0; + $this->resolvedGroups = $hasChildren ? new \SplObjectStorage() : null; + + foreach ($groups->groups as $group) { + if ($validateDataGraph) { + $validator->atPath('data')->validate($data, null, $group); + } + + if ($groupedConstraints = self::getConstraintsInGroups($constraints, $group)) { + $validator->atPath('data')->validate($data, $groupedConstraints, $group); + } + + foreach ($form->all() as $field) { + if ($field->isSubmitted()) { + // remember to validate this field is one group only + // otherwise resolving the groups would reuse the same + // sequence recursively, thus some fields could fail + // in different steps without breaking early enough + $this->resolvedGroups[$field] = (array) $group; + $validator->atPath(sprintf($fieldPropertyPath, $field->getPropertyPath()))->validate($field, $formConstraint); } } + + if ($violationsCount < $this->context->getViolations()->count()) { + break; + } + } + + if ($hasChildren) { + // destroy storage at the end of the sequence to avoid memory leaks + $this->resolvedGroups = null; } } else { + if ($validateDataGraph) { + $validator->atPath('data')->validate($data, null, $groups); + } + foreach ($constraints as $constraint) { // For the "Valid" constraint, validate the data in all groups if ($constraint instanceof Valid) { - $validator->atPath('data')->validate($form->getData(), $constraint, $groups); + $validator->atPath('data')->validate($data, $constraint, $groups); continue; } @@ -88,7 +116,7 @@ public function validate($form, Constraint $formConstraint) // matching group foreach ($groups as $group) { if (\in_array($group, $constraint->groups)) { - $validator->atPath('data')->validate($form->getData(), $constraint, $group); + $validator->atPath('data')->validate($data, $constraint, $group); // Prevent duplicate validation if (!$constraint instanceof Composite) { @@ -147,7 +175,7 @@ public function validate($form, Constraint $formConstraint) * * @return string|GroupSequence|(string|GroupSequence)[] The validation groups */ - private static function getValidationGroups(FormInterface $form) + private function getValidationGroups(FormInterface $form) { // Determine the clicked button of the complete form tree $clickedButton = null; @@ -171,6 +199,10 @@ private static function getValidationGroups(FormInterface $form) return self::resolveValidationGroups($groups, $form); } + if (isset($this->resolvedGroups[$form])) { + return $this->resolvedGroups[$form]; + } + $form = $form->getParent(); } while (null !== $form); @@ -197,4 +229,11 @@ private static function resolveValidationGroups($groups, FormInterface $form) return (array) $groups; } + + private static function getConstraintsInGroups($constraints, $group) + { + return array_filter($constraints, static function (Constraint $constraint) use ($group) { + return \in_array($group, $constraint->groups, true); + }); + } } diff --git a/src/Symfony/Component/Form/Resources/config/validation.xml b/src/Symfony/Component/Form/Resources/config/validation.xml index cbd586b915451..b2b935442d467 100644 --- a/src/Symfony/Component/Form/Resources/config/validation.xml +++ b/src/Symfony/Component/Form/Resources/config/validation.xml @@ -7,7 +7,7 @@ - + diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index e19620e790f7c..5181e4122516e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -401,8 +401,8 @@ public function testHandleGroupSequenceValidationGroups() $form = $this->getCompoundForm($object, $options); $form->submit([]); - $this->expectValidateAt(0, 'data', $object, new GroupSequence(['group1', 'group2'])); - $this->expectValidateAt(1, 'data', $object, new GroupSequence(['group1', 'group2'])); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); $this->validator->validate($form, new Form()); @@ -756,6 +756,39 @@ public function testCompositeConstraintValidatedInEachGroup() $this->assertSame('data[field2]', $context->getViolations()[1]->getPropertyPath()); } + public function testCompositeConstraintValidatedInSequence() + { + $form = $this->getCompoundForm([], [ + 'constraints' => [ + new Collection([ + 'field1' => new NotBlank([ + 'groups' => ['field1'], + ]), + 'field2' => new NotBlank([ + 'groups' => ['field2'], + ]), + ]), + ], + 'validation_groups' => new GroupSequence(['field1', 'field2']), + ]) + ->add($this->getForm('field1')) + ->add($this->getForm('field2')) + ; + + $form->submit([ + 'field1' => '', + 'field2' => '', + ]); + + $context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator()); + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + + $this->assertCount(1, $context->getViolations()); + $this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage()); + $this->assertSame('data[field1]', $context->getViolations()[0]->getPropertyPath()); + } + protected function createValidator() { return new FormValidator(); @@ -784,7 +817,7 @@ private function getForm($name = 'name', $dataClass = null, array $options = []) private function getCompoundForm($data, array $options = []) { - return $this->getBuilder('name', \get_class($data), $options) + return $this->getBuilder('name', \is_object($data) ? \get_class($data) : null, $options) ->setData($data) ->setCompound(true) ->setDataMapper(new PropertyPathMapper()) diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 57f92b6574e3b..4c90cc6316db8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -12,15 +12,19 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\Form; use Symfony\Component\Form\Forms; use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait; use Symfony\Component\Form\Tests\Extension\Core\Type\FormTypeTest; use Symfony\Component\Form\Tests\Extension\Core\Type\TextTypeTest; -use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface; use Symfony\Component\Validator\Validation; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest @@ -64,14 +68,69 @@ public function testGroupSequenceWithConstraintsOption() ->add('field', TextTypeTest::TESTED_TYPE, [ 'constraints' => [ new Length(['min' => 10, 'groups' => ['First']]), - new Email(['groups' => ['Second']]), + new NotBlank(['groups' => ['Second']]), ], ]) ; $form->submit(['field' => 'wrong']); - $this->assertCount(1, $form->getErrors(true)); + $errors = $form->getErrors(true); + + $this->assertCount(1, $errors); + $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); + } + + public function testManyFieldsGroupSequenceWithConstraintsOption() + { + $formMetadata = new ClassMetadata(Form::class); + $authorMetadata = (new ClassMetadata(Author::class)) + ->addPropertyConstraint('firstName', new NotBlank(['groups' => 'Second'])) + ; + $metadataFactory = $this->createMock(MetadataFactoryInterface::class); + $metadataFactory->expects($this->any()) + ->method('getMetadataFor') + ->willReturnCallback(static function ($classOrObject) use ($formMetadata, $authorMetadata) { + if (Author::class === $classOrObject || $classOrObject instanceof Author) { + return $authorMetadata; + } + + if (Form::class === $classOrObject || $classOrObject instanceof Form) { + return $formMetadata; + } + + return new ClassMetadata(\is_string($classOrObject) ? $classOrObject : \get_class($classOrObject)); + }) + ; + + $validator = Validation::createValidatorBuilder() + ->setMetadataFactory($metadataFactory) + ->getValidator() + ; + $form = Forms::createFormFactoryBuilder() + ->addExtension(new ValidatorExtension($validator)) + ->getFormFactory() + ->create(FormTypeTest::TESTED_TYPE, new Author(), (['validation_groups' => new GroupSequence(['First', 'Second'])])) + ->add('firstName', TextTypeTest::TESTED_TYPE) + ->add('lastName', TextTypeTest::TESTED_TYPE, [ + 'constraints' => [ + new Length(['min' => 10, 'groups' => ['First']]), + ], + ]) + ->add('australian', TextTypeTest::TESTED_TYPE, [ + 'constraints' => [ + new NotBlank(['groups' => ['Second']]), + ], + ]) + ; + + $form->submit(['firstName' => '', 'lastName' => 'wrong_1', 'australian' => '']); + + $errors = $form->getErrors(true); + + $this->assertCount(1, $errors); + $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); + $this->assertSame('children[lastName].data', $errors[0]->getCause()->getPropertyPath()); } protected function createForm(array $options = []) diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php index 136086a5e5ba8..cb9b93abdbf61 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -13,6 +13,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Validator\Constraints\Form as FormConstraint; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser; @@ -20,6 +22,8 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormFactoryBuilder; use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\Validator\Constraints\GroupSequence; +use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Mapping\CascadingStrategy; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -49,6 +53,8 @@ public function test2Dot5ValidationApi() $this->assertCount(1, $metadata->getConstraints()); $this->assertInstanceOf(FormConstraint::class, $metadata->getConstraints()[0]); + $this->assertSame(CascadingStrategy::NONE, $metadata->cascadingStrategy); + $this->assertSame(TraversalStrategy::IMPLICIT, $metadata->traversalStrategy); $this->assertSame(CascadingStrategy::CASCADE, $metadata->getPropertyMetadata('children')[0]->cascadingStrategy); $this->assertSame(TraversalStrategy::IMPLICIT, $metadata->getPropertyMetadata('children')[0]->traversalStrategy); } @@ -86,7 +92,53 @@ public function testFieldConstraintsInvalidateFormIfFieldIsSubmitted() $this->assertFalse($form->get('baz')->isValid()); } - private function createForm($type) + public function testFieldsValidateInSequence() + { + $form = $this->createForm(FormType::class, null, [ + 'validation_groups' => new GroupSequence(['group1', 'group2']), + ]) + ->add('foo', TextType::class, [ + 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], + ]) + ->add('bar', TextType::class, [ + 'constraints' => [new NotBlank(['groups' => ['group2']])], + ]) + ; + + $form->submit(['foo' => 'invalid', 'bar' => null]); + + $errors = $form->getErrors(true); + + $this->assertCount(1, $errors); + $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); + } + + public function testFieldsValidateInSequenceWithNestedGroupsArray() + { + $form = $this->createForm(FormType::class, null, [ + 'validation_groups' => new GroupSequence([['group1', 'group2'], 'group3']), + ]) + ->add('foo', TextType::class, [ + 'constraints' => [new Length(['min' => 10, 'groups' => ['group1']])], + ]) + ->add('bar', TextType::class, [ + 'constraints' => [new Length(['min' => 10, 'groups' => ['group2']])], + ]) + ->add('baz', TextType::class, [ + 'constraints' => [new NotBlank(['groups' => ['group3']])], + ]) + ; + + $form->submit(['foo' => 'invalid', 'bar' => 'invalid', 'baz' => null]); + + $errors = $form->getErrors(true); + + $this->assertCount(2, $errors); + $this->assertInstanceOf(Length::class, $errors[0]->getCause()->getConstraint()); + $this->assertInstanceOf(Length::class, $errors[1]->getCause()->getConstraint()); + } + + private function createForm($type, $data = null, array $options = []) { $validator = Validation::createValidatorBuilder() ->setMetadataFactory(new LazyLoadingMetadataFactory(new StaticMethodLoader())) @@ -95,7 +147,7 @@ private function createForm($type) $formFactoryBuilder->addExtension(new ValidatorExtension($validator)); $formFactory = $formFactoryBuilder->getFormFactory(); - return $formFactory->create($type); + return $formFactory->create($type, $data, $options); } } From 46c278316c7306de7e323866072e3c4422b14d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Talha=20Zekeriya=20Durmu=C5=9F?= Date: Fri, 17 Apr 2020 19:05:47 +0300 Subject: [PATCH 37/51] [SecurityBundle] fix accepting env vars in remember-me configurations --- .../DependencyInjection/Security/Factory/RememberMeFactory.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php index 624deb0283fd7..cd7202019c2eb 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php @@ -146,8 +146,6 @@ public function addConfiguration(NodeDefinition $node) foreach ($this->options as $name => $value) { if (\is_bool($value)) { $builder->booleanNode($name)->defaultValue($value); - } elseif (\is_int($value)) { - $builder->integerNode($name)->defaultValue($value); } else { $builder->scalarNode($name)->defaultValue($value); } From 0cbca19edcd7d64ae18f7d1a02c0e1ba2aaa8132 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 18 Apr 2020 22:23:17 +0200 Subject: [PATCH 38/51] [HttpFoundation] workaround PHP bug in the session module --- .../Session/Storage/Handler/AbstractSessionHandler.php | 9 +++++++++ .../Session/Storage/Handler/Fixtures/regenerate.expected | 1 + 2 files changed, 10 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php index ec59d895ce3a3..c80da20466b4a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -71,6 +71,15 @@ public function validateId($sessionId) $this->prefetchData = $this->read($sessionId); $this->prefetchId = $sessionId; + if (\PHP_VERSION_ID < 70317 || (70400 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70405)) { + // work around https://bugs.php.net/79413 + foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { + if (!isset($frame['class']) && isset($frame['function']) && \in_array($frame['function'], ['session_regenerate_id', 'session_create_id'], true)) { + return '' === $this->prefetchData; + } + } + } + return '' !== $this->prefetchData; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.expected b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.expected index baa5f2f6f5cb0..d825f44f7cb86 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.expected +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.expected @@ -11,6 +11,7 @@ validateId read doRead: abc|i:123; read +doRead: abc|i:123; write doWrite: abc|i:123; From 4bda68a9a25f2a99addd2e53315f3a1523b25848 Mon Sep 17 00:00:00 2001 From: stoccc Date: Sun, 19 Apr 2020 23:34:01 +0200 Subject: [PATCH 39/51] Update LdapBindAuthenticationProvider.php --- .../Provider/LdapBindAuthenticationProvider.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/LdapBindAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/LdapBindAuthenticationProvider.php index 00092c431373c..e68649801b1cc 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/LdapBindAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/LdapBindAuthenticationProvider.php @@ -87,9 +87,8 @@ protected function checkAuthentication(UserInterface $user, UsernamePasswordToke } try { - $username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_DN); - if ($this->queryString) { + $username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_FILTER); $query = str_replace('{username}', $username, $this->queryString); $result = $this->ldap->query($this->dnString, $query)->execute(); if (1 !== $result->count()) { @@ -98,6 +97,7 @@ protected function checkAuthentication(UserInterface $user, UsernamePasswordToke $dn = $result[0]->getDn(); } else { + $username = $this->ldap->escape($username, '', LdapInterface::ESCAPE_DN); $dn = str_replace('{username}', $username, $this->dnString); } From 76072c6424840a137bd9cad609db3d7a79ce7ab0 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Mon, 20 Apr 2020 18:08:44 +0200 Subject: [PATCH 40/51] [FrameworkBundle] Fix session.attribute_bag service definition --- .../Bundle/FrameworkBundle/Resources/config/session.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 9f3a5b78c1e2e..9080af9379899 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -41,7 +41,8 @@ - + + attributes From 3c24cfecdd3ae40ffdc4450bc2f6a9df8f18ff88 Mon Sep 17 00:00:00 2001 From: Dimitri Gritsajuk Date: Wed, 22 Apr 2020 12:28:41 +0200 Subject: [PATCH 41/51] [Form] apply automatically step=1 for datetime-local input --- .../Form/Extension/Core/Type/DateTimeType.php | 8 +++++ .../Extension/Core/Type/DateTimeTypeTest.php | 31 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index 4a7c75b2652a0..fc701d5203dce 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -203,6 +203,14 @@ public function buildView(FormView $view, FormInterface $form, array $options) // * the html5 is set to true if ($options['html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'datetime-local'; + + // we need to force the browser to display the seconds by + // adding the HTML attribute step if not already defined. + // Otherwise the browser will not display and so not send the seconds + // therefore the value will always be considered as invalid. + if ($options['with_seconds'] && !isset($view->vars['attr']['step'])) { + $view->vars['attr']['step'] = 1; + } } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php index 8af524f1fceae..53edd21b91c5d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -444,6 +444,37 @@ public function testDontPassHtml5TypeIfNotSingleText() $this->assertArrayNotHasKey('type', $view->vars); } + public function testSingleTextWidgetWithSecondsShouldHaveRightStepAttribute() + { + $view = $this->factory + ->create(static::TESTED_TYPE, null, [ + 'widget' => 'single_text', + 'with_seconds' => true, + ]) + ->createView() + ; + + $this->assertArrayHasKey('step', $view->vars['attr']); + $this->assertEquals(1, $view->vars['attr']['step']); + } + + public function testSingleTextWidgetWithSecondsShouldNotOverrideStepAttribute() + { + $view = $this->factory + ->create(static::TESTED_TYPE, null, [ + 'widget' => 'single_text', + 'with_seconds' => true, + 'attr' => [ + 'step' => 30, + ], + ]) + ->createView() + ; + + $this->assertArrayHasKey('step', $view->vars['attr']); + $this->assertEquals(30, $view->vars['attr']['step']); + } + public function testDateTypeChoiceErrorsBubbleUp() { $error = new FormError('Invalid!'); From 5a7208481d777b78ad3038d54f3e10d9a8a21397 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 23 Apr 2020 23:34:23 +0200 Subject: [PATCH 42/51] [Cache] skip APCu in chains when the backend is disabled --- src/Symfony/Component/Cache/Adapter/AbstractAdapter.php | 7 ++----- src/Symfony/Component/Cache/Adapter/ChainAdapter.php | 3 +++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index dad0dc8f66f55..ce1262ae17557 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -14,7 +14,6 @@ use Psr\Cache\CacheItemInterface; use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerInterface; -use Psr\Log\NullLogger; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\ResettableInterface; @@ -116,14 +115,12 @@ public static function createSystemCache($namespace, $defaultLifetime, $version, if (null !== $logger) { $fs->setLogger($logger); } - if (!self::$apcuSupported) { + if (!self::$apcuSupported || (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN))) { return $fs; } $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version); - if ('cli' === \PHP_SAPI && !filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) { - $apcu->setLogger(new NullLogger()); - } elseif (null !== $logger) { + if (null !== $logger) { $apcu->setLogger($logger); } diff --git a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php index 0080db711bce7..c2c9f4a8008ac 100644 --- a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php @@ -46,6 +46,9 @@ public function __construct(array $adapters, $defaultLifetime = 0) if (!$adapter instanceof CacheItemPoolInterface) { throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class)); } + if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) { + continue; // skip putting APCu in the chain when the backend is disabled + } if ($adapter instanceof AdapterInterface) { $this->adapters[] = $adapter; From e27ed28bae708102b011c7a8c4744e01b0173d14 Mon Sep 17 00:00:00 2001 From: Massimiliano Arione Date: Thu, 23 Apr 2020 09:31:24 +0200 Subject: [PATCH 43/51] fix compatibility with phpunit 9 --- .../Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php | 7 +++++-- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 4 ++++ src/Symfony/Bridge/PhpUnit/composer.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 69bbcfc09eab0..77693421bacdd 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -46,9 +46,12 @@ class SymfonyTestsListenerTrait public function __construct(array $mockedNamespaces = array()) { if (class_exists('PHPUnit_Util_Blacklist')) { - \PHPUnit_Util_Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait'] = 2; + \PHPUnit_Util_Blacklist::$blacklistedClassNames[__CLASS__] = 2; + } elseif (method_exists(Blacklist::class, 'addDirectory')) { + (new BlackList())->getBlacklistedDirectories(); + Blacklist::addDirectory(\dirname(\dirname((new \ReflectionClass(__CLASS__))->getFileName()))); } else { - Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait'] = 2; + Blacklist::$blacklistedClassNames[__CLASS__] = 2; } $warn = false; diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index d2c23f2025b74..3043daababc1d 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -126,6 +126,10 @@ if (!class_exists('SymfonyBlacklistPhpunit', false)) { if (class_exists('PHPUnit_Util_Blacklist')) { PHPUnit_Util_Blacklist::$blacklistedClassNames['SymfonyBlacklistPhpunit'] = 1; PHPUnit_Util_Blacklist::$blacklistedClassNames['SymfonyBlacklistSimplePhpunit'] = 1; +} elseif (method_exists('PHPUnit\Util\Blacklist', 'addDirectory')) { + (new PHPUnit\Util\BlackList())->getBlacklistedDirectories(); + PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass('SymfonyBlacklistPhpunit'))->getFileName())); + PHPUnit\Util\Blacklist::addDirectory(\dirname((new \ReflectionClass('SymfonyBlacklistSimplePhpunit'))->getFileName())); } else { PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyBlacklistPhpunit'] = 1; PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyBlacklistSimplePhpunit'] = 1; diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json index f7d9492613ab6..30b3cc23f63d8 100644 --- a/src/Symfony/Bridge/PhpUnit/composer.json +++ b/src/Symfony/Bridge/PhpUnit/composer.json @@ -24,7 +24,7 @@ "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" }, "conflict": { - "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0|<6.4,>=6.0" + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0|<6.4,>=6.0|9.1.2" }, "autoload": { "files": [ "bootstrap.php" ], From 734d97bdccca86bc5c669713b34dc84b9855229f Mon Sep 17 00:00:00 2001 From: sdkawata Date: Fri, 24 Apr 2020 19:16:04 +0900 Subject: [PATCH 44/51] [YAML] escape DEL(\x7f) --- src/Symfony/Component/Yaml/Escaper.php | 4 +++- src/Symfony/Component/Yaml/Tests/DumperTest.php | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Yaml/Escaper.php b/src/Symfony/Component/Yaml/Escaper.php index 4d3ce244c2ada..9413d7a2c4804 100644 --- a/src/Symfony/Component/Yaml/Escaper.php +++ b/src/Symfony/Component/Yaml/Escaper.php @@ -22,7 +22,7 @@ class Escaper { // Characters that would cause a dumped string to require double quoting. - const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; + const REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\x7f|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9"; // Mapping arrays for escaping a double quoted string. The backslash is // first to ensure proper escaping because str_replace operates iteratively @@ -33,6 +33,7 @@ class Escaper "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f", + "\x7f", "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9", ]; private static $escaped = ['\\\\', '\\"', '\\\\', '\\"', @@ -40,6 +41,7 @@ class Escaper '\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f', '\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17', '\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f', + '\\x7f', '\\N', '\\_', '\\L', '\\P', ]; diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index bb2a575eebdab..e4dc49f331d72 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -289,6 +289,7 @@ public function getEscapeSequences() 'double-quote' => ['"', "'\"'"], 'slash' => ['/', '/'], 'backslash' => ['\\', '\\'], + 'del' => ["\x7f", '"\x7f"'], 'next-line' => ["\xC2\x85", '"\\N"'], 'non-breaking-space' => ["\xc2\xa0", '"\\_"'], 'line-separator' => ["\xE2\x80\xA8", '"\\L"'], From 6dce90d47bc8ff944d670f6b6d418efb1506fa33 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 24 Apr 2020 14:56:41 +0200 Subject: [PATCH 45/51] [PhpUnitBridge] Use COMPOSER_BINARY env var if available --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 3043daababc1d..92d4d6994af9c 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -65,11 +65,13 @@ foreach ($defaultEnvs as $envName => $envValue) { } } -$COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') - || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`)) - || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer`) : `which composer 2> /dev/null`)) - ? (file_get_contents($COMPOSER, false, null, 0, 18) === '#!/usr/bin/env php' ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang - : 'composer'; +if (false === $COMPOSER = \getenv('COMPOSER_BINARY')) { + $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') + || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`)) + || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer`) : `which composer 2> /dev/null`)) + ? (file_get_contents($COMPOSER, false, null, 0, 18) === '#!/usr/bin/env php' ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang + : 'composer'; +} if (false === $SYMFONY_PHPUNIT_REMOVE = getenv('SYMFONY_PHPUNIT_REMOVE')) { $SYMFONY_PHPUNIT_REMOVE = 'phpspec/prophecy symfony/yaml'; From e721cfd65cbf4f42702d904757dd3ecc0da8c0a2 Mon Sep 17 00:00:00 2001 From: Alessandro Lai Date: Fri, 24 Apr 2020 16:08:51 +0200 Subject: [PATCH 46/51] Improve dirname usage --- src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 77693421bacdd..e260fb8dd6854 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -49,7 +49,7 @@ public function __construct(array $mockedNamespaces = array()) \PHPUnit_Util_Blacklist::$blacklistedClassNames[__CLASS__] = 2; } elseif (method_exists(Blacklist::class, 'addDirectory')) { (new BlackList())->getBlacklistedDirectories(); - Blacklist::addDirectory(\dirname(\dirname((new \ReflectionClass(__CLASS__))->getFileName()))); + Blacklist::addDirectory(\dirname((new \ReflectionClass(__CLASS__))->getFileName(), 2)); } else { Blacklist::$blacklistedClassNames[__CLASS__] = 2; } From fb3aaefbf2c301744395c5b6e75806f9ade29951 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 26 Apr 2020 10:08:16 +0200 Subject: [PATCH 47/51] add tests for the ConstraintViolationBuilder class --- .../ConstraintViolationBuilderTest.php | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/Symfony/Component/Validator/Tests/Violation/ConstraintViolationBuilderTest.php diff --git a/src/Symfony/Component/Validator/Tests/Violation/ConstraintViolationBuilderTest.php b/src/Symfony/Component/Validator/Tests/Violation/ConstraintViolationBuilderTest.php new file mode 100644 index 0000000000000..4121dc2622e96 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Violation/ConstraintViolationBuilderTest.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Violation; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\IdentityTranslator; +use Symfony\Component\Validator\Constraints\Valid; +use Symfony\Component\Validator\ConstraintViolation; +use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\Test\ForwardCompatTestTrait; +use Symfony\Component\Validator\Violation\ConstraintViolationBuilder; + +class ConstraintViolationBuilderTest extends TestCase +{ + use ForwardCompatTestTrait; + + private $root; + private $violations; + private $messageTemplate = '%value% is invalid'; + private $builder; + + private function doSetUp() + { + $this->root = [ + 'data' => [ + 'foo' => 'bar', + 'baz' => 'foobar', + ], + ]; + $this->violations = new ConstraintViolationList(); + $this->builder = new ConstraintViolationBuilder($this->violations, new Valid(), $this->messageTemplate, [], $this->root, 'data', 'foo', new IdentityTranslator()); + } + + public function testAddViolation() + { + $this->builder->addViolation(); + + $this->assertViolationEquals(new ConstraintViolation($this->messageTemplate, $this->messageTemplate, [], $this->root, 'data', 'foo', null, null, new Valid())); + } + + public function testAppendPropertyPath() + { + $this->builder + ->atPath('foo') + ->addViolation(); + + $this->assertViolationEquals(new ConstraintViolation($this->messageTemplate, $this->messageTemplate, [], $this->root, 'data.foo', 'foo', null, null, new Valid())); + } + + public function testAppendMultiplePropertyPaths() + { + $this->builder + ->atPath('foo') + ->atPath('bar') + ->addViolation(); + + $this->assertViolationEquals(new ConstraintViolation($this->messageTemplate, $this->messageTemplate, [], $this->root, 'data.foo.bar', 'foo', null, null, new Valid())); + } + + public function testCodeCanBeSet() + { + $this->builder + ->setCode(5) + ->addViolation(); + + $this->assertViolationEquals(new ConstraintViolation($this->messageTemplate, $this->messageTemplate, [], $this->root, 'data', 'foo', null, 5, new Valid())); + } + + public function testCauseCanBeSet() + { + $cause = new \LogicException(); + + $this->builder + ->setCause($cause) + ->addViolation(); + + $this->assertViolationEquals(new ConstraintViolation($this->messageTemplate, $this->messageTemplate, [], $this->root, 'data', 'foo', null, null, new Valid(), $cause)); + } + + private function assertViolationEquals(ConstraintViolation $expectedViolation) + { + $this->assertCount(1, $this->violations); + + $violation = $this->violations->get(0); + + $this->assertSame($expectedViolation->getMessage(), $violation->getMessage()); + $this->assertSame($expectedViolation->getMessageTemplate(), $violation->getMessageTemplate()); + $this->assertSame($expectedViolation->getParameters(), $violation->getParameters()); + $this->assertSame($expectedViolation->getPlural(), $violation->getPlural()); + $this->assertSame($expectedViolation->getRoot(), $violation->getRoot()); + $this->assertSame($expectedViolation->getPropertyPath(), $violation->getPropertyPath()); + $this->assertSame($expectedViolation->getInvalidValue(), $violation->getInvalidValue()); + $this->assertSame($expectedViolation->getCode(), $violation->getCode()); + $this->assertEquals($expectedViolation->getConstraint(), $violation->getConstraint()); + $this->assertSame($expectedViolation->getCause(), $violation->getCause()); + } +} From 89fb0799cd950867d998d9d3de60d3761f2ac76b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Beurlet?= Date: Fri, 24 Apr 2020 18:48:20 +0200 Subject: [PATCH 48/51] [WebProfilerBundle] changed label of peak memory usage in the time & memory panels (MB into MiB) --- .../Resources/views/Collector/memory.html.twig | 6 +++--- .../Resources/views/Collector/time.html.twig | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig index 268f8fdc7e3f6..49878a72d5d65 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/memory.html.twig @@ -5,18 +5,18 @@ {% set status_color = (collector.memory / 1024 / 1024) > 50 ? 'yellow' : '' %} {{ include('@WebProfiler/Icon/memory.svg') }} {{ '%.1f'|format(collector.memory / 1024 / 1024) }} - MB + MiB {% endset %} {% set text %}
Peak memory usage - {{ '%.1f'|format(collector.memory / 1024 / 1024) }} MB + {{ '%.1f'|format(collector.memory / 1024 / 1024) }} MiB
PHP memory limit - {{ collector.memoryLimit == -1 ? 'Unlimited' : '%.0f MB'|format(collector.memoryLimit / 1024 / 1024) }} + {{ collector.memoryLimit == -1 ? 'Unlimited' : '%.0f MiB'|format(collector.memoryLimit / 1024 / 1024) }}
{% endset %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig index dd95b511b40ea..a9fd19225d2d6 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig @@ -64,7 +64,7 @@ {% if profile.collectors.memory %}
- {{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} MB + {{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} MiB Peak memory usage
{% endif %} @@ -386,7 +386,7 @@ ctx.fillStyle = "#444"; ctx.font = "12px sans-serif"; text = event.name; - ms = " " + (event.duration < 1 ? event.duration : parseInt(event.duration, 10)) + " ms / " + event.memory + " MB"; + ms = " " + (event.duration < 1 ? event.duration : parseInt(event.duration, 10)) + " ms / " + event.memory + " MiB"; if (x + event.starttime * ratio + ctx.measureText(text + ms).width > width) { ctx.textAlign = "end"; ctx.font = "10px sans-serif"; From 99080bdbe7afb344c7d96dcd30393e564767c799 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Apr 2020 19:40:55 +0200 Subject: [PATCH 49/51] updated CHANGELOG for 3.4.40 --- CHANGELOG-3.4.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index 8e7a8406ff391..7fc92f86eb326 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG-3.4.md @@ -7,6 +7,35 @@ 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.40 (2020-04-28) + + * bug #36566 [PhpUnitBridge] Use COMPOSER_BINARY env var if available (fancyweb) + * bug #36560 [YAML] escape DEL(\x7f) (sdkawata) + * bug #36539 [PhpUnitBridge] fix compatibility with phpunit 9 (garak) + * bug #36555 [Cache] skip APCu in chains when the backend is disabled (nicolas-grekas) + * bug #36523 [Form] apply automatically step=1 for datetime-local input (ottaviano) + * bug #36498 [Security/Core] fix escape for username in LdapBindAuthenticationProvider.php (stoccc) + * bug #36506 [FrameworkBundle] Fix session.attribute_bag service definition (fancyweb) + * bug #36490 [HttpFoundation] workaround PHP bug in the session module (nicolas-grekas) + * bug #36483 [SecurityBundle] fix accepting env vars in remember-me configurations (zek) + * bug #36343 [Form] Fixed handling groups sequence validation (HeahDude) + * bug #36460 [Cache] Avoid memory leak in TraceableAdapter::reset() (lyrixx) + * bug #36411 [Form] RepeatedType should always have inner types mapped (biozshock) + * bug #36441 [DI] fix loading defaults when using the PHP-DSL (nicolas-grekas) + * bug #36434 [HttpKernel] silence E_NOTICE triggered since PHP 7.4 (xabbuh) + * bug #36365 [Validator] Fixed default group for nested composite constraints (HeahDude) + * bug #35591 [Validator] do not merge constraints within interfaces (greedyivan) + * bug #36375 [Workflow] Use a strict comparison when retrieving raw marking in MarkingStore (lyrixx) + * bug #36305 [PropertyInfo][ReflectionExtractor] Check the array mutator prefixes last when the property is singular (fancyweb) + * bug #35656 [HttpFoundation] Fixed session migration with custom cookie lifetime (Guite) + * bug #36315 [WebProfilerBundle] Support for Content Security Policy style-src-elem and script-src-elem in WebProfiler (ampaze) + * bug #36286 [Validator] Allow URL-encoded special characters in basic auth part of URLs (cweiske) + * bug #36332 [Serializer] Fix unitialized properties (from PHP 7.4.2) when serializing context for the cache key (alanpoulain) + * bug #36239 [HttpKernel][LoggerDataCollector] Prevent keys collisions in the sanitized logs processing (fancyweb) + * bug #36245 [Validator] Fixed calling getters before resolving groups (HeahDude) + * bug #36252 [Security/Http] Allow setting cookie security settings for delete_cookies (wouterj) + * bug #36261 [FrameworkBundle] revert to legacy wiring of the session when circular refs are detected (nicolas-grekas) + * 3.4.39 (2020-03-30) * bug #36216 [Validator] Assert Valid with many groups (phucwan91) From 1822b065d7f83101f3d6e098e60a60c4b313bb20 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Apr 2020 19:41:24 +0200 Subject: [PATCH 50/51] update CONTRIBUTORS for 3.4.40 --- CONTRIBUTORS.md | 77 ++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 53a2faec2f45f..449973d7578eb 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -24,10 +24,10 @@ Symfony is the result of the work of many people who made the code better - Kris Wallsmith (kriswallsmith) - Yonel Ceruto (yonelceruto) - Hugo Hamon (hhamon) + - Wouter de Jong (wouterj) + - Thomas Calvet (fancyweb) - Abdellatif Ait boudad (aitboudad) - Samuel ROZE (sroze) - - Thomas Calvet (fancyweb) - - Wouter de Jong (wouterj) - Romain Neutron (romain) - Pascal Borreli (pborreli) - Joseph Bielawski (stloyd) @@ -37,8 +37,8 @@ Symfony is the result of the work of many people who made the code better - Jules Pietri (heah) - Hamza Amrouche (simperfit) - Martin Hasoň (hason) - - Jeremy Mikola (jmikola) - Jérémy DERUSSÉ (jderusse) + - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) @@ -50,9 +50,9 @@ Symfony is the result of the work of many people who made the code better - Lynn van der Berg (kjarli) - Diego Saint Esteben (dosten) - Matthias Pigulla (mpdude) + - Pierre du Plessis (pierredup) - Alexandre Salomé (alexandresalome) - William Durand (couac) - - Pierre du Plessis (pierredup) - ornicar - Dany Maillard (maidmaid) - Francis Besset (francisbesset) @@ -69,10 +69,10 @@ Symfony is the result of the work of many people who made the code better - Gabriel Ostrolucký (gadelat) - Miha Vrhovnik - David Maicher (dmaicher) - - Diego Saint Esteben (dii3g0) - Gábor Egyed (1ed) - - Titouan Galopin (tgalopin) + - Diego Saint Esteben (dii3g0) - Jan Schädlich (jschaedl) + - Titouan Galopin (tgalopin) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Mathieu Piot (mpiot) @@ -110,6 +110,7 @@ Symfony is the result of the work of many people who made the code better - Baptiste Clavié (talus) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) + - Sebastiaan Stok (sstok) - Chris Wilkinson (thewilkybarkid) - Brice BERNARD (brikou) - marc.weistroff @@ -119,7 +120,6 @@ Symfony is the result of the work of many people who made the code better - lenar - Alexander Schwenn (xelaris) - Włodzimierz Gajda (gajdaw) - - Sebastiaan Stok (sstok) - Adrien Brault (adrienbrault) - Jacob Dreesen (jdreesen) - Florian Voutzinos (florianv) @@ -139,18 +139,18 @@ Symfony is the result of the work of many people who made the code better - Przemysław Bogusz (przemyslaw-bogusz) - Eric GELOEN (gelo) - Lars Strojny (lstrojny) + - Massimiliano Arione (garak) - Jannik Zschiesche (apfelbox) - Robert Schönthal (digitalkaoz) - Gregor Harlan (gharlan) - Florian Lonqueu-Brochard (florianlb) + - Alexander Schranz (alexander-schranz) - Gabriel Caruso (carusogabriel) - Stefano Sala (stefano.sala) - Evgeniy (ewgraf) - - Massimiliano Arione (garak) - Julien Falque (julienfalque) - Vincent AUBERT (vincent) - Juti Noppornpitak (shiroyuki) - - Alexander Schranz (alexander-schranz) - Anthony MARTIN (xurudragon) - Tigran Azatyan (tigranazatyan) - Sebastian Hörl (blogsh) @@ -176,6 +176,7 @@ Symfony is the result of the work of many people who made the code better - Richard van Laak (rvanlaak) - Richard Shank (iampersistent) - Thomas Rabaix (rande) + - Ahmed TAILOULOUTE (ahmedtai) - Vincent Touzet (vincenttouzet) - jeremyFreeAgent (jeremyfreeagent) - Rouven Weßling (realityking) @@ -198,6 +199,7 @@ Symfony is the result of the work of many people who made the code better - James Halsall (jaitsu) - Matthieu Napoli (mnapoli) - Florent Mata (fmata) + - Antoine Makdessi (amakdessi) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) @@ -213,15 +215,18 @@ Symfony is the result of the work of many people who made the code better - Dennis Benkert (denderello) - DQNEO - Andre Rømcke (andrerom) + - Saif (╯°□°)╯ (azjezz) - mcfedr (mcfedr) - Gary PEGEOT (gary-p) - Ruben Gonzalez (rubenrua) - Benjamin Dulau (dbenjamin) + - Jan Rosier (rosier) - Andreas Braun - Mathieu Lemoine (lemoinem) - Christian Schmidt - Andreas Hucks (meandmymonkey) - Tom Van Looy (tvlooy) + - Guillaume Pédelagrabe - Noel Guilbert (noel) - Anthony GRASSIOT (antograssiot) - Stadly @@ -233,7 +238,7 @@ Symfony is the result of the work of many people who made the code better - Nikolay Labinskiy (e-moe) - Martin Schuhfuß (usefulthink) - apetitpa - - Antoine Makdessi (amakdessi) + - Maxime Helias (maxhelias) - Matthieu Bontemps (mbontemps) - apetitpa - Pierre Minnieur (pminnieur) @@ -243,14 +248,13 @@ Symfony is the result of the work of many people who made the code better - Laurent VOULLEMIER (lvo) - Michael Lee (zerustech) - Matthieu Auger (matthieuauger) - - Ahmed TAILOULOUTE (ahmedtai) + - Mathias Arlaud (mtarld) - Leszek Prabucki (l3l0) - Fabien Bourigault (fbourigault) - François Zaninotto (fzaninotto) - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) - - Jan Rosier (rosier) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - Michele Orselli (orso) @@ -270,7 +274,6 @@ Symfony is the result of the work of many people who made the code better - Marcel Beerta (mazen) - Christopher Hertel (chertel) - Ruud Kamphuis (ruudk) - - Maxime Helias (maxhelias) - Pavel Batanov (scaytrase) - Mantis Development - David Prévot @@ -283,7 +286,6 @@ Symfony is the result of the work of many people who made the code better - Lorenz Schori - Sébastien Lavoie (lavoiesl) - Dariusz - - Saif (╯°□°)╯ (azjezz) - Dmitrii Poddubnyi (karser) - Michael Babker (mbabker) - Francois Zaninotto @@ -307,7 +309,6 @@ Symfony is the result of the work of many people who made the code better - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA - Patrick McDougle (patrick-mcdougle) - - Guillaume Pédelagrabe - Alif Rachmawadi - Anton Chernikov (anton_ch1989) - Kristen Gilden (kgilden) @@ -336,9 +337,9 @@ Symfony is the result of the work of many people who made the code better - Jeroen Spee (jeroens) - Nikita Konstantinov - Wodor Wodorski + - Olivier Dolbeau (odolbeau) - Thomas Lallement (raziel057) - Colin O'Dell (colinodell) - - Mathias Arlaud (mtarld) - Giorgio Premi - renanbr - Alex Rock (pierstoval) @@ -364,6 +365,7 @@ Symfony is the result of the work of many people who made the code better - Vilius Grigaliūnas - David Badura (davidbadura) - Chad Sikorra (chadsikorra) + - Alan Poulain (alanpoulain) - Chris Smith (cs278) - Thomas Bisignani (toma) - Florian Klein (docteurklein) @@ -413,7 +415,6 @@ Symfony is the result of the work of many people who made the code better - Thomas Royer (cydonia7) - Nicolas LEFEVRE (nicoweb) - alquerci - - Olivier Dolbeau (odolbeau) - Oleg Andreyev - Mateusz Sip (mateusz_sip) - Francesco Levorato @@ -426,6 +427,7 @@ Symfony is the result of the work of many people who made the code better - Tomasz Kowalczyk (thunderer) - Artur Eshenbrener - Timo Bakx (timobakx) + - Antonio Pauletich (x-coder264) - Thomas Perez (scullwm) - Felix Labrecque - Yaroslav Kiliba @@ -443,7 +445,6 @@ Symfony is the result of the work of many people who made the code better - Eduardo Gulias (egulias) - giulio de donato (liuggio) - ShinDarth - - Alan Poulain - Stéphane PY (steph_py) - Philipp Kräutli (pkraeutli) - Grzegorz (Greg) Zdanowski (kiler129) @@ -540,10 +541,10 @@ Symfony is the result of the work of many people who made the code better - Martijn Cuppens - Vlad Gregurco (vgregurco) - Boris Vujicic (boris.vujicic) + - Artem Lopata - Chris Sedlmayr (catchamonkey) - Kamil Kokot (pamil) - Seb Koelen - - Antonio Pauletich (x-coder264) - Christoph Mewes (xrstf) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) @@ -553,14 +554,17 @@ Symfony is the result of the work of many people who made the code better - Jonas Flodén (flojon) - Tobias Weichart - Gonzalo Vilaseca (gonzalovilaseca) + - Daniel STANCU - Tarmo Leppänen (tarlepp) - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) - Marek Pietrzak - Luc Vieillescazes (iamluc) - franek (franek) + - soyuka - Raulnet - Christian Wahler + - Giso Stallenberg (gisostallenberg) - Gintautas Miselis - Rob Bast - Roberto Espinoza (respinoza) @@ -599,6 +603,7 @@ Symfony is the result of the work of many people who made the code better - Philipp Rieber (bicpi) - Manuel de Ruiter (manuel) - Nathanael Noblet (gnat) + - Dimitri Gritsajuk (ottaviano) - nikos.sotiropoulos - Eduardo Oliveira (entering) - Ilya Antipenko (aivus) @@ -744,6 +749,7 @@ Symfony is the result of the work of many people who made the code better - Benjamin Cremer (bcremer) - Javier López (loalf) - Reinier Kip + - Jérôme Tamarelle (jtamarelle-prismamedia) - Geoffrey Brier (geoffrey-brier) - Alexandre Parent - Vladimir Tsykun @@ -778,7 +784,6 @@ Symfony is the result of the work of many people who made the code better - Miquel Rodríguez Telep (mrtorrent) - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski - - Artem Lopata - M. Vondano - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) @@ -786,10 +791,10 @@ Symfony is the result of the work of many people who made the code better - Richard Bradley - Ulumuddin Yunus (joenoez) - rtek + - Ivan Grigoriev - Johann Saunier (prophet777) - Sergey (upyx) - Andreas Erhard - - Giso Stallenberg (gisostallenberg) - Michael Devery (mickadoo) - Antoine Corcy - Ahmed Ashraf (ahmedash95) @@ -810,6 +815,7 @@ Symfony is the result of the work of many people who made the code better - Cameron Porter - Hossein Bukhamsin - Oliver Hoff + - William Arslett - Christian Sciberras (uuf6429) - Disparity - origaminal @@ -856,7 +862,6 @@ Symfony is the result of the work of many people who made the code better - Markus Fasselt (digilist) - Julien DIDIER (juliendidier) - Dominik Ritter (dritter) - - Dimitri Gritsajuk (ottaviano) - Sebastian Grodzicki (sgrodzicki) - Mohamed Gamal - Jeroen van den Enden (stoefke) @@ -871,6 +876,7 @@ Symfony is the result of the work of many people who made the code better - Yuen-Chi Lian - Tarjei Huse (tarjei) - Besnik Br + - Axel Guckelsberger (guite) - Jose Gonzalez - Jonathan (jls-esokia) - Oleksii Zhurbytskyi @@ -881,12 +887,14 @@ Symfony is the result of the work of many people who made the code better - Jakub Kulhan (jakubkulhan) - Shaharia Azam - avorobiev + - stoccc - Grégoire Penverne (gpenverne) - Venu - Lars Vierbergen - Jonatan Männchen - Dennis Hotson - Andrew Tchircoff (andrewtch) + - Ahmed Raafat - michaelwilliams - Martin Kirilov - 1emming @@ -894,6 +902,7 @@ Symfony is the result of the work of many people who made the code better - Tri Pham (phamuyentri) - Jordan Deitch - Casper Valdemar Poulsen + - Laurent Masforné (heisenberg) - Josiah (josiah) - Guillaume Verstraete (versgui) - Greg ORIOL @@ -961,10 +970,8 @@ Symfony is the result of the work of many people who made the code better - Laurent Bassin (lbassin) - andrey1s - Abhoryo - - Daniel STANCU - Fabian Vogler (fabian) - Korvin Szanto - - soyuka - Stéphan Kochen - Arjan Keeman - Alaattin Kahramanlar (alaattin) @@ -1133,6 +1140,7 @@ Symfony is the result of the work of many people who made the code better - Nicolas Le Goff (nlegoff) - Ben Oman - Chris de Kok + - Eduard Bulava (nonanerz) - Lorenzo Millucci - Andreas Kleemann - Manuele Menozzi @@ -1150,6 +1158,7 @@ Symfony is the result of the work of many people who made the code better - hamza - dantleech - Bastien DURAND (deamon) + - Kajetan Kołtuniak (kajtii) - Sander Goossens (sandergo90) - Rudy Onfroy - Tero Alén (tero) @@ -1237,7 +1246,6 @@ Symfony is the result of the work of many people who made the code better - Benjamin Paap (benjaminpaap) - Claus Due (namelesscoder) - Christian - - William Arslett - Denis Golubovskiy (bukashk0zzz) - Sergii Smertin (nfx) - Mikkel Paulson @@ -1246,6 +1254,7 @@ Symfony is the result of the work of many people who made the code better - Marc Duboc (icemad) - Matthias Krauser (mkrauser) - Martynas Narbutas + - Nilmar Sanchez Muguercia - Toon Verwerft (veewee) - Bailey Parker - Eddie Jaoude @@ -1289,6 +1298,7 @@ Symfony is the result of the work of many people who made the code better - Stephen Clouse - e-ivanov - Michał (bambucha15) + - Benjamin Dos Santos - Einenlum - Jérémy Jarrié (gagnar) - Jochen Bayer (jocl) @@ -1344,6 +1354,7 @@ Symfony is the result of the work of many people who made the code better - Klaus Purer - arnaud (arnooo999) - Gilles Doge (gido) + - Oscar Esteve (oesteve) - abulford - Philipp Kretzschmar - antograssiot @@ -1367,7 +1378,6 @@ Symfony is the result of the work of many people who made the code better - Derek Lambert - MightyBranch - Kacper Gunia (cakper) - - Jérôme Tamarelle (jtamarelle-prismamedia) - Peter Thompson (petert82) - error56 - Felicitus @@ -1392,6 +1402,7 @@ Symfony is the result of the work of many people who made the code better - Nyro (nyro) - Marco - Marc Torres + - Mark Spink - Alberto Aldegheri - Dmitri Petmanson - heccjj @@ -1412,7 +1423,6 @@ Symfony is the result of the work of many people who made the code better - David Négrier (moufmouf) - Quique Porta (quiqueporta) - mohammadreza honarkhah - - stoccc - Andrea Quintino (dirk39) - Tomasz Szymczyk (karion) - Alex Vasilchenko @@ -1468,7 +1478,6 @@ Symfony is the result of the work of many people who made the code better - Walter Dal Mut (wdalmut) - abluchet - Ruud Arentsen - - Ahmed Raafat - Harald Tollefsen - Matthieu - Albin Kerouaton @@ -1504,7 +1513,6 @@ Symfony is the result of the work of many people who made the code better - Antal Áron (antalaron) - Vašek Purchart (vasek-purchart) - Janusz Jabłoński (yanoosh) - - Ivan Grigoriev - Fleuv - Sandro Hopf - Łukasz Makuch @@ -1522,6 +1530,7 @@ Symfony is the result of the work of many people who made the code better - Philip Frank - David Brooks - Lance McNearney + - Serhiy Lunak (slunak) - Giorgio Premi - Aurélien Fontaine - ncou @@ -1531,6 +1540,7 @@ Symfony is the result of the work of many people who made the code better - Matt Daum (daum) - Alberto Pirovano (geezmo) - Pete Mitchell (peterjmit) + - phuc vo (phucwan) - Tom Corrigan (tomcorrigan) - Luis Galeas - Bogdan Scordaliu @@ -1543,7 +1553,6 @@ Symfony is the result of the work of many people who made the code better - WedgeSama - Felds Liscia - Chihiro Adachi (chihiro-adachi) - - Axel Guckelsberger (guite) - Raphaëll Roussel - Tadcka - Beth Binkovitz @@ -1651,6 +1660,7 @@ Symfony is the result of the work of many people who made the code better - Flavian (2much) - Gautier Deuette - mike + - tadas - Kirk Madera - Keith Maika - Mephistofeles @@ -1834,6 +1844,7 @@ Symfony is the result of the work of many people who made the code better - alefranz - David Barratt - Andrea Giannantonio + - Dries Vints - Pavel.Batanov - avi123 - Pavel Prischepa @@ -1900,6 +1911,7 @@ Symfony is the result of the work of many people who made the code better - Yannick Warnier (ywarnier) - Kevin Decherf - Jason Woods + - Christian Weiske - Maria Grazia Patteri - klemens - dened @@ -2149,6 +2161,7 @@ Symfony is the result of the work of many people who made the code better - Evgeniy Tetenchuk - Sjoerd Adema - Shrey Puranik + - Evgeniy Koval - Lars Moelleken - dasmfm - Mathias Geat @@ -2208,6 +2221,7 @@ Symfony is the result of the work of many people who made the code better - Niklas Keller - Andras Debreczeni - Vladimir Sazhin + - Michel Bardelmeijer - Tomas Kmieliauskas - Billie Thompson - lol768 @@ -2241,6 +2255,7 @@ Symfony is the result of the work of many people who made the code better - Michael Schneider - Cédric Bertolini - n-aleha + - Talha Zekeriya Durmuş - Anatol Belski - Anderson Müller - Şəhriyar İmanov @@ -2268,6 +2283,7 @@ Symfony is the result of the work of many people who made the code better - Neophy7e - bokonet - Arrilot + - ampaze - Markus Staab - Pierre-Louis LAUNAY - djama @@ -2417,6 +2433,7 @@ Symfony is the result of the work of many people who made the code better - Michal Čihař (mcihar) - Matt Drollette (mdrollette) - Adam Monsen (meonkeys) + - Mike Milano (mmilano) - diego aguiar (mollokhan) - Hugo Monteiro (monteiro) - Ala Eddine Khefifi (nayzo) From f59e0e9c236c1b31440e120be2fd0a2794509310 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 28 Apr 2020 19:41:38 +0200 Subject: [PATCH 51/51] updated VERSION for 3.4.40 --- 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 9422d90e9ee9b..dc9cc048eb53f 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.40-DEV'; + const VERSION = '3.4.40'; const VERSION_ID = 30440; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; const RELEASE_VERSION = 40; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021';