From c73b042044ef26e0d9b7eec2c6ea9db0a74759ef Mon Sep 17 00:00:00 2001 From: Bogdan Scordaliu Date: Tue, 22 Oct 2019 10:54:04 +0200 Subject: [PATCH 01/65] bug symfony#28179 [DomCrawler] Skip disabled fields processing in Form --- src/Symfony/Component/DomCrawler/Form.php | 10 +--------- .../Component/DomCrawler/Tests/FormTest.php | 16 ++++++++-------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index 87ab31485f397..375ee531c4a0e 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -89,10 +89,6 @@ public function getValues() { $values = []; foreach ($this->fields->all() as $name => $field) { - if ($field->isDisabled()) { - continue; - } - if (!$field instanceof Field\FileFormField && $field->hasValue()) { $values[$name] = $field->getValue(); } @@ -115,10 +111,6 @@ public function getFiles() $files = []; foreach ($this->fields->all() as $name => $field) { - if ($field->isDisabled()) { - continue; - } - if ($field instanceof Field\FileFormField) { $files[$name] = $field->getValue(); } @@ -463,7 +455,7 @@ private function initialize() private function addField(\DOMElement $node) { - if (!$node->hasAttribute('name') || !$node->getAttribute('name')) { + if (!$node->hasAttribute('name') || !$node->getAttribute('name') || $node->hasAttribute('disabled')) { return; } diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 504a9bd4251d9..50f5a120eaa5f 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -148,12 +148,12 @@ public function testConstructorHandlesFormValues() public function testMultiValuedFields() { $form = $this->createForm('
- - - - - - + + + + + +
'); @@ -216,10 +216,10 @@ public function provideInitializeValues() [], ], [ - 'takes into account disabled input fields', + 'skips disabled input fields', ' ', - ['foo' => ['InputFormField', 'foo']], + [], ], [ 'appends the submitted button value', From c9072c70efcceb151915cd0909ff819a13228d1c Mon Sep 17 00:00:00 2001 From: Leevi Graham Date: Fri, 25 Oct 2019 21:23:51 +1100 Subject: [PATCH 02/65] Check value isset to avoid PHP notice --- src/Symfony/Component/Console/Style/SymfonyStyle.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index 4291ada8f6cd6..02e9b471b8e61 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -229,7 +229,7 @@ public function choice($question, array $choices, $default = null) { if (null !== $default) { $values = array_flip($choices); - $default = $values[$default]; + $default = isset($values[$default]) ? $values[$default] : $default; } return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); From 4939f0e32304329207e4248de35406bfc0c23c61 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 25 Oct 2019 19:00:46 -0400 Subject: [PATCH 03/65] Fix handling of empty_data's \Closure value in Date/Time form types --- .../Form/Extension/Core/Type/DateTimeType.php | 16 ++++++++-- .../Form/Extension/Core/Type/DateType.php | 30 ++++++++++++++----- .../Form/Extension/Core/Type/TimeType.php | 20 +++++++++++-- .../Extension/Core/Type/DateTimeTypeTest.php | 10 +++++++ .../Extension/Core/Type/DateTypeTest.php | 10 +++++++ .../Extension/Core/Type/TimeTypeTest.php | 10 +++++++ 6 files changed, 83 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index 04b0221fdc632..6edefd622e477 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -107,7 +107,17 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'invalid_message_parameters', ])); - if (isset($emptyData['date'])) { + if ($emptyData instanceof \Closure) { + $lazyEmptyData = static function ($option) use ($emptyData) { + return static function (FormInterface $form) use ($emptyData, $option) { + $emptyData = $emptyData($form->getParent()); + + return isset($emptyData[$option]) ? $emptyData[$option] : ''; + }; + }; + + $dateOptions['empty_data'] = $lazyEmptyData('date'); + } elseif (isset($emptyData['date'])) { $dateOptions['empty_data'] = $emptyData['date']; } @@ -126,7 +136,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'invalid_message_parameters', ])); - if (isset($emptyData['time'])) { + if ($emptyData instanceof \Closure) { + $timeOptions['empty_data'] = $lazyEmptyData('time'); + } elseif (isset($emptyData['time'])) { $timeOptions['empty_data'] = $emptyData['time']; } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index 464c262c13680..5aea4418b200d 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -81,14 +81,28 @@ public function buildForm(FormBuilderInterface $builder, array $options) // so we need to handle the cascade setting here $emptyData = $builder->getEmptyData() ?: []; - if (isset($emptyData['year'])) { - $yearOptions['empty_data'] = $emptyData['year']; - } - if (isset($emptyData['month'])) { - $monthOptions['empty_data'] = $emptyData['month']; - } - if (isset($emptyData['day'])) { - $dayOptions['empty_data'] = $emptyData['day']; + if ($emptyData instanceof \Closure) { + $lazyEmptyData = static function ($option) use ($emptyData) { + return static function (FormInterface $form) use ($emptyData, $option) { + $emptyData = $emptyData($form->getParent()); + + return isset($emptyData[$option]) ? $emptyData[$option] : ''; + }; + }; + + $yearOptions['empty_data'] = $lazyEmptyData('year'); + $monthOptions['empty_data'] = $lazyEmptyData('month'); + $dayOptions['empty_data'] = $lazyEmptyData('day'); + } else { + if (isset($emptyData['year'])) { + $yearOptions['empty_data'] = $emptyData['year']; + } + if (isset($emptyData['month'])) { + $monthOptions['empty_data'] = $emptyData['month']; + } + if (isset($emptyData['day'])) { + $dayOptions['empty_data'] = $emptyData['day']; + } } if (isset($options['invalid_message'])) { diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php index c88bea812bdab..f0b5ac2ac4df8 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimeType.php @@ -76,7 +76,17 @@ public function buildForm(FormBuilderInterface $builder, array $options) // so we need to handle the cascade setting here $emptyData = $builder->getEmptyData() ?: []; - if (isset($emptyData['hour'])) { + if ($emptyData instanceof \Closure) { + $lazyEmptyData = static function ($option) use ($emptyData) { + return static function (FormInterface $form) use ($emptyData, $option) { + $emptyData = $emptyData($form->getParent()); + + return isset($emptyData[$option]) ? $emptyData[$option] : ''; + }; + }; + + $hourOptions['empty_data'] = $lazyEmptyData('hour'); + } elseif (isset($emptyData['hour'])) { $hourOptions['empty_data'] = $emptyData['hour']; } @@ -143,14 +153,18 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->add('hour', self::$widgets[$options['widget']], $hourOptions); if ($options['with_minutes']) { - if (isset($emptyData['minute'])) { + if ($emptyData instanceof \Closure) { + $minuteOptions['empty_data'] = $lazyEmptyData('minute'); + } elseif (isset($emptyData['minute'])) { $minuteOptions['empty_data'] = $emptyData['minute']; } $builder->add('minute', self::$widgets[$options['widget']], $minuteOptions); } if ($options['with_seconds']) { - if (isset($emptyData['second'])) { + if ($emptyData instanceof \Closure) { + $secondOptions['empty_data'] = $lazyEmptyData('second'); + } elseif (isset($emptyData['second'])) { $secondOptions['empty_data'] = $emptyData['second']; } $builder->add('second', self::$widgets[$options['widget']], $secondOptions); 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 e3f3b729d3ec7..8af524f1fceae 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormInterface; class DateTimeTypeTest extends BaseTypeTest { @@ -608,6 +609,9 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa ]); $form->submit(null); + if ($emptyData instanceof \Closure) { + $emptyData = $emptyData($form); + } $this->assertSame($emptyData, $form->getViewData()); $this->assertEquals($expectedData, $form->getNormData()); $this->assertEquals($expectedData, $form->getData()); @@ -616,11 +620,17 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa public function provideEmptyData() { $expectedData = \DateTime::createFromFormat('Y-m-d H:i', '2018-11-11 21:23'); + $lazyEmptyData = static function (FormInterface $form) { + return $form->getConfig()->getCompound() ? ['date' => ['year' => '2018', 'month' => '11', 'day' => '11'], 'time' => ['hour' => '21', 'minute' => '23']] : '2018-11-11T21:23:00'; + }; return [ 'Simple field' => ['single_text', '2018-11-11T21:23:00', $expectedData], 'Compound text field' => ['text', ['date' => ['year' => '2018', 'month' => '11', 'day' => '11'], 'time' => ['hour' => '21', 'minute' => '23']], $expectedData], 'Compound choice field' => ['choice', ['date' => ['year' => '2018', 'month' => '11', 'day' => '11'], 'time' => ['hour' => '21', 'minute' => '23']], $expectedData], + 'Simple field lazy' => ['single_text', $lazyEmptyData, $expectedData], + 'Compound text field lazy' => ['text', $lazyEmptyData, $expectedData], + 'Compound choice field lazy' => ['choice', $lazyEmptyData, $expectedData], ]; } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index 96c74fe0e4209..cb2c2d0a30bdc 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormInterface; use Symfony\Component\Intl\Util\IntlTestHelper; class DateTypeTest extends BaseTypeTest @@ -985,6 +986,9 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa ]); $form->submit(null); + if ($emptyData instanceof \Closure) { + $emptyData = $emptyData($form); + } $this->assertSame($emptyData, $form->getViewData()); $this->assertEquals($expectedData, $form->getNormData()); $this->assertEquals($expectedData, $form->getData()); @@ -993,11 +997,17 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa public function provideEmptyData() { $expectedData = \DateTime::createFromFormat('Y-m-d H:i:s', '2018-11-11 00:00:00'); + $lazyEmptyData = static function (FormInterface $form) { + return $form->getConfig()->getCompound() ? ['year' => '2018', 'month' => '11', 'day' => '11'] : '2018-11-11'; + }; return [ 'Simple field' => ['single_text', '2018-11-11', $expectedData], 'Compound text fields' => ['text', ['year' => '2018', 'month' => '11', 'day' => '11'], $expectedData], 'Compound choice fields' => ['choice', ['year' => '2018', 'month' => '11', 'day' => '11'], $expectedData], + 'Simple field lazy' => ['single_text', $lazyEmptyData, $expectedData], + 'Compound text fields lazy' => ['text', $lazyEmptyData, $expectedData], + 'Compound choice fields lazy' => ['choice', $lazyEmptyData, $expectedData], ]; } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php index e89dd8d20c9e1..1f0797f000db4 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormInterface; class TimeTypeTest extends BaseTypeTest { @@ -785,6 +786,9 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa ]); $form->submit(null); + if ($emptyData instanceof \Closure) { + $emptyData = $emptyData($form); + } $this->assertSame($emptyData, $form->getViewData()); $this->assertEquals($expectedData, $form->getNormData()); $this->assertEquals($expectedData, $form->getData()); @@ -793,11 +797,17 @@ public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedDa public function provideEmptyData() { $expectedData = \DateTime::createFromFormat('Y-m-d H:i', '1970-01-01 21:23'); + $lazyEmptyData = static function (FormInterface $form) { + return $form->getConfig()->getCompound() ? ['hour' => '21', 'minute' => '23'] : '21:23'; + }; return [ 'Simple field' => ['single_text', '21:23', $expectedData], 'Compound text field' => ['text', ['hour' => '21', 'minute' => '23'], $expectedData], 'Compound choice field' => ['choice', ['hour' => '21', 'minute' => '23'], $expectedData], + 'Simple field lazy' => ['single_text', $lazyEmptyData, $expectedData], + 'Compound text field lazy' => ['text', $lazyEmptyData, $expectedData], + 'Compound choice field lazy' => ['choice', $lazyEmptyData, $expectedData], ]; } } From 2797867ae95f6c532960078b38315ba59bc2c21f Mon Sep 17 00:00:00 2001 From: Arman Hosseini Date: Thu, 2 Jan 2020 00:53:08 +0330 Subject: [PATCH 04/65] Check non-null type for numeric type $maxAge and $sharedAge can both be zero --- .../FrameworkBundle/Controller/TemplateController.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php index f72d556f60b51..52086ef8dd223 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php @@ -75,17 +75,17 @@ public function templateAction($template, $maxAge = null, $sharedAge = null, $pr throw new \LogicException('You can not use the TemplateController if the Templating Component or the Twig Bundle are not available.'); } - if ($maxAge) { + if (null !== $maxAge) { $response->setMaxAge($maxAge); } - if ($sharedAge) { + if (null !== $sharedAge) { $response->setSharedMaxAge($sharedAge); } if ($private) { $response->setPrivate(); - } elseif (false === $private || (null === $private && ($maxAge || $sharedAge))) { + } elseif (false === $private || (null === $private && (null !== $maxAge || null !== $sharedAge))) { $response->setPublic(); } From bdf02c0a7ebd160872116ddb1a15528e2f1ba585 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Tue, 14 Jan 2020 09:16:44 +0100 Subject: [PATCH 05/65] [Yaml][Inline] Fail properly on empty object tag and empty const tag --- src/Symfony/Component/Yaml/Inline.php | 15 ++++++- .../Component/Yaml/Tests/InlineTest.php | 43 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 73aba3cb8b0dc..7ad4a64ead967 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -506,7 +506,12 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = [] if ('!php/const' === $key) { $key .= self::parseScalar($mapping, $flags, [':', ' '], $i, false, [], true); - $key = self::evaluateScalar($key, $flags); + if ('!php/const:' === $key && ':' !== $mapping[$i]) { + $key = ''; + --$i; + } else { + $key = self::evaluateScalar($key, $flags); + } } if (':' !== $key && false === $i = strpos($mapping, ':', $i)) { @@ -692,6 +697,10 @@ private static function evaluateScalar($scalar, $flags, $references = []) return null; case 0 === strpos($scalar, '!php/object'): if (self::$objectSupport) { + if (!isset($scalar[12])) { + return false; + } + return unserialize(self::parseScalar(substr($scalar, 12))); } @@ -717,6 +726,10 @@ private static function evaluateScalar($scalar, $flags, $references = []) return null; case 0 === strpos($scalar, '!php/const'): if (self::$constantSupport) { + if (!isset($scalar[11])) { + return ''; + } + $i = 0; if (\defined($const = self::parseScalar(substr($scalar, 11), 0, null, $i, false))) { return \constant($const); diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 54372d69505bc..5b55451e19eb3 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -799,4 +799,47 @@ public function getTestsForOctalNumbers() 'negative octal number' => [-28, '-034'], ]; } + + /** + * @dataProvider phpObjectTagWithEmptyValueProvider + */ + public function testPhpObjectWithEmptyValue($expected, $value) + { + $this->assertSame($expected, Inline::parse($value, Yaml::PARSE_OBJECT)); + } + + public function phpObjectTagWithEmptyValueProvider() + { + return [ + [false, '!php/object'], + [false, '!php/object '], + [false, '!php/object '], + [[false], '[!php/object]'], + [[false], '[!php/object ]'], + [[false, 'foo'], '[!php/object , foo]'], + ]; + } + + /** + * @dataProvider phpConstTagWithEmptyValueProvider + */ + public function testPhpConstTagWithEmptyValue($expected, $value) + { + $this->assertSame($expected, Inline::parse($value, Yaml::PARSE_CONSTANT)); + } + + public function phpConstTagWithEmptyValueProvider() + { + return [ + ['', '!php/const'], + ['', '!php/const '], + ['', '!php/const '], + [[''], '[!php/const]'], + [[''], '[!php/const ]'], + [['', 'foo'], '[!php/const , foo]'], + [['' => 'foo'], '{!php/const: foo}'], + [['' => 'foo'], '{!php/const : foo}'], + [['' => 'foo', 'bar' => 'ccc'], '{!php/const : foo, bar: ccc}'], + ]; + } } From 6aec78035115e6459cd10147368e6c4c59596c39 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 21 Jan 2020 14:12:52 +0100 Subject: [PATCH 06/65] bumped Symfony version to 3.4.38 --- 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 463b49174fbf3..87f102a0fb26d 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.37'; - const VERSION_ID = 30437; + const VERSION = '3.4.38-DEV'; + const VERSION_ID = 30438; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; - const RELEASE_VERSION = 37; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 38; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From 28cd964ac9490e9817ede736bb9c582fa19c69cb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 23 Jan 2020 11:22:20 +0100 Subject: [PATCH 07/65] Fix testing with mongodb --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8574ad92a0f98..4251d2fa0247c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -182,7 +182,7 @@ before_install: echo extension = $ext_cache >> $INI elif [[ $PHP = 7.* ]]; then tfold ext.apcu tpecl apcu-5.1.17 apcu.so $INI - tfold ext.mongodb tpecl mongodb-1.6.0alpha1 mongodb.so $INI + tfold ext.mongodb tpecl mongodb-1.6.0 mongodb.so $INI fi done @@ -279,7 +279,7 @@ install: fi phpenv global ${PHP/hhvm*/hhvm} if [[ $PHP = 7.* ]]; then - ([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; composer config platform.ext-mongodb 1.6.0; composer require --dev --no-update mongodb/mongodb) + ([[ $deps ]] && cd src/Symfony/Component/HttpFoundation; composer config platform.ext-mongodb 1.6.0; composer require --dev --no-update mongodb/mongodb ~1.5.0) fi tfold 'composer update' $COMPOSER_UP if [[ $TRAVIS_PHP_VERSION = 5.* || $TRAVIS_PHP_VERSION = hhvm* ]]; then From 6b2db6dc305cd1fc08ed3761e5ee1c5a1e210a83 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Sat, 25 Jan 2020 13:51:20 +0100 Subject: [PATCH 08/65] Improved error message when no supported user provider is found --- src/Symfony/Component/Security/Core/User/ChainUserProvider.php | 2 +- .../Component/Security/Http/Firewall/ContextListener.php | 2 +- .../Security/Http/RememberMe/AbstractRememberMeServices.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/Core/User/ChainUserProvider.php b/src/Symfony/Component/Security/Core/User/ChainUserProvider.php index 5ea8150a3017e..ad93e53f146ba 100644 --- a/src/Symfony/Component/Security/Core/User/ChainUserProvider.php +++ b/src/Symfony/Component/Security/Core/User/ChainUserProvider.php @@ -91,7 +91,7 @@ public function refreshUser(UserInterface $user) $e->setUsername($user->getUsername()); throw $e; } else { - throw new UnsupportedUserException(sprintf('The account "%s" is not supported.', \get_class($user))); + throw new UnsupportedUserException(sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', \get_class($user))); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 6a05ee5175cb1..af912c446c249 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -238,7 +238,7 @@ protected function refreshUser(TokenInterface $token) return null; } - throw new \RuntimeException(sprintf('There is no user provider for user "%s".', $userClass)); + throw new \RuntimeException(sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', $userClass)); } private function safelyUnserialize($serializedToken) diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index bf69f3012b6ba..e47e1812212cf 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -239,7 +239,7 @@ final protected function getUserProvider($class) } } - throw new UnsupportedUserException(sprintf('There is no user provider that supports class "%s".', $class)); + throw new UnsupportedUserException(sprintf('There is no user provider for user "%s". Shouldn\'t the "supportsClass()" method of your user provider return true for this classname?', $class)); } /** From 9cbfad5853d29eaaa9e9796c489fcead7a441fd4 Mon Sep 17 00:00:00 2001 From: Signor Pedro <53906348+signor-pedro@users.noreply.github.com> Date: Wed, 29 Jan 2020 11:07:44 +0100 Subject: [PATCH 09/65] [DependencyInjection] #35505 Fix typo in test name Rename testThrowsExceptionWhenAddServiceOnACompiledContainer to testNoExceptionWhenAddServiceOnACompiledContainer. --- .../DependencyInjection/Tests/ContainerBuilderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 53d62a58d214f..75b9305ff32df 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1090,7 +1090,7 @@ public function testThrowsExceptionWhenSetServiceOnACompiledContainer() $container->set('a', new \stdClass()); } - public function testThrowsExceptionWhenAddServiceOnACompiledContainer() + public function testNoExceptionWhenAddServiceOnACompiledContainer() { $container = new ContainerBuilder(); $container->compile(); From ad5f427bed252b5f98616c7aa4d62868e260fdc2 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 10 Jan 2020 23:18:38 +0000 Subject: [PATCH 10/65] =?UTF-8?q?[HttpKernel]=C2=A0Fix=20stale-if-error=20?= =?UTF-8?q?behavior,=20add=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Component/HttpFoundation/Response.php | 2 +- .../HttpKernel/HttpCache/HttpCache.php | 30 +++- .../Tests/HttpCache/HttpCacheTest.php | 162 ++++++++++++++++++ 3 files changed, 190 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 26e3a3378efa0..0f361bac3d3c2 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -649,7 +649,7 @@ public function isImmutable() } /** - * Returns true if the response must be revalidated by caches. + * Returns true if the response must be revalidated by shared caches once it has become stale. * * This method indicates that the response must not be served stale by a * cache in any circumstance without first revalidating with the origin. diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index da60e74642cb4..3471758525a31 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -452,13 +452,37 @@ protected function forward(Request $request, $catch = false, Response $entry = n // always a "master" request (as the real master request can be in cache) $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $catch); - // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC - if (null !== $entry && \in_array($response->getStatusCode(), [500, 502, 503, 504])) { + /* + * Support stale-if-error given on Responses or as a config option. + * RFC 7234 summarizes in Section 4.2.4 (but also mentions with the individual + * Cache-Control directives) that + * + * A cache MUST NOT generate a stale response if it is prohibited by an + * explicit in-protocol directive (e.g., by a "no-store" or "no-cache" + * cache directive, a "must-revalidate" cache-response-directive, or an + * applicable "s-maxage" or "proxy-revalidate" cache-response-directive; + * see Section 5.2.2). + * + * https://tools.ietf.org/html/rfc7234#section-4.2.4 + * + * We deviate from this in one detail, namely that we *do* serve entries in the + * stale-if-error case even if they have a `s-maxage` Cache-Control directive. + */ + if (null !== $entry + && \in_array($response->getStatusCode(), [500, 502, 503, 504]) + && !$entry->headers->hasCacheControlDirective('no-cache') + && !$entry->mustRevalidate() + ) { if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { $age = $this->options['stale_if_error']; } - if (abs($entry->getTtl()) < $age) { + /* + * stale-if-error gives the (extra) time that the Response may be used *after* it has become stale. + * So we compare the time the $entry has been sitting in the cache already with the + * time it was fresh plus the allowed grace period. + */ + if ($entry->getAge() <= $entry->getMaxAge() + $age) { $this->record($request, 'stale-if-error'); return $entry; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index ef201de6cf15f..cac06a80e59da 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -1523,6 +1523,168 @@ public function testUsesOriginalRequestForSurrogate() // Surrogate request $cache->handle($request, HttpKernelInterface::SUB_REQUEST); } + + public function testStaleIfErrorMustNotResetLifetime() + { + // Make sure we don't accidentally treat the response as fresh (revalidated) again + // when stale-if-error handling kicks in. + + $responses = [ + [ + 'status' => 200, + 'body' => 'OK', + // This is cacheable and can be used in stale-if-error cases: + 'headers' => ['Cache-Control' => 'public, max-age=10', 'ETag' => 'some-etag'], + ], + [ + 'status' => 500, + 'body' => 'FAIL', + 'headers' => [], + ], + [ + 'status' => 500, + 'body' => 'FAIL', + 'headers' => [], + ], + ]; + + $this->setNextResponses($responses); + $this->cacheConfig['stale_if_error'] = 10; + + $this->request('GET', '/'); // warm cache + + sleep(15); // now the entry is stale, but still within the grace period (10s max-age + 10s stale-if-error) + + $this->request('GET', '/'); // hit backend error + $this->assertEquals(200, $this->response->getStatusCode()); // stale-if-error saved the day + $this->assertEquals(15, $this->response->getAge()); + + sleep(10); // now we're outside the grace period + + $this->request('GET', '/'); // hit backend error + $this->assertEquals(500, $this->response->getStatusCode()); // fail + } + + /** + * @dataProvider getResponseDataThatMayBeServedStaleIfError + */ + public function testResponsesThatMayBeUsedStaleIfError($responseHeaders, $sleepBetweenRequests = null) + { + $responses = [ + [ + 'status' => 200, + 'body' => 'OK', + 'headers' => $responseHeaders, + ], + [ + 'status' => 500, + 'body' => 'FAIL', + 'headers' => [], + ], + ]; + + $this->setNextResponses($responses); + $this->cacheConfig['stale_if_error'] = 10; // after stale, may be served for 10s + + $this->request('GET', '/'); // warm cache + + if ($sleepBetweenRequests) { + sleep($sleepBetweenRequests); + } + + $this->request('GET', '/'); // hit backend error + + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('OK', $this->response->getContent()); + $this->assertTraceContains('stale-if-error'); + } + + public function getResponseDataThatMayBeServedStaleIfError() + { + // All data sets assume that a 10s stale-if-error grace period has been configured + yield 'public, max-age expired' => [['Cache-Control' => 'public, max-age=60'], 65]; + yield 'public, validateable with ETag, no TTL' => [['Cache-Control' => 'public', 'ETag' => 'some-etag'], 5]; + yield 'public, validateable with Last-Modified, no TTL' => [['Cache-Control' => 'public', 'Last-Modified' => 'yesterday'], 5]; + yield 'public, s-maxage will be served stale-if-error, even if the RFC mandates otherwise' => [['Cache-Control' => 'public, s-maxage=20'], 25]; + } + + /** + * @dataProvider getResponseDataThatMustNotBeServedStaleIfError + */ + public function testResponsesThatMustNotBeUsedStaleIfError($responseHeaders, $sleepBetweenRequests = null) + { + $responses = [ + [ + 'status' => 200, + 'body' => 'OK', + 'headers' => $responseHeaders, + ], + [ + 'status' => 500, + 'body' => 'FAIL', + 'headers' => [], + ], + ]; + + $this->setNextResponses($responses); + $this->cacheConfig['stale_if_error'] = 10; // after stale, may be served for 10s + $this->cacheConfig['strict_smaxage'] = true; // full RFC compliance for this feature + + $this->request('GET', '/'); // warm cache + + if ($sleepBetweenRequests) { + sleep($sleepBetweenRequests); + } + + $this->request('GET', '/'); // hit backend error + + $this->assertEquals(500, $this->response->getStatusCode()); + } + + public function getResponseDataThatMustNotBeServedStaleIfError() + { + // All data sets assume that a 10s stale-if-error grace period has been configured + yield 'public, no TTL but beyond grace period' => [['Cache-Control' => 'public'], 15]; + yield 'public, validateable with ETag, no TTL but beyond grace period' => [['Cache-Control' => 'public', 'ETag' => 'some-etag'], 15]; + yield 'public, validateable with Last-Modified, no TTL but beyond grace period' => [['Cache-Control' => 'public', 'Last-Modified' => 'yesterday'], 15]; + yield 'public, stale beyond grace period' => [['Cache-Control' => 'public, max-age=10'], 30]; + + // Cache-control values that prohibit serving stale responses or responses without positive validation - + // see https://tools.ietf.org/html/rfc7234#section-4.2.4 and + // https://tools.ietf.org/html/rfc7234#section-5.2.2 + yield 'no-cache requires positive validation' => [['Cache-Control' => 'public, no-cache', 'ETag' => 'some-etag']]; + yield 'no-cache requires positive validation, even if fresh' => [['Cache-Control' => 'public, no-cache, max-age=10']]; + yield 'must-revalidate requires positive validation once stale' => [['Cache-Control' => 'public, max-age=10, must-revalidate'], 15]; + yield 'proxy-revalidate requires positive validation once stale' => [['Cache-Control' => 'public, max-age=10, proxy-revalidate'], 15]; + } + + public function testStaleIfErrorWhenStrictSmaxageDisabled() + { + $responses = [ + [ + 'status' => 200, + 'body' => 'OK', + 'headers' => ['Cache-Control' => 'public, s-maxage=20'], + ], + [ + 'status' => 500, + 'body' => 'FAIL', + 'headers' => [], + ], + ]; + + $this->setNextResponses($responses); + $this->cacheConfig['stale_if_error'] = 10; + $this->cacheConfig['strict_smaxage'] = false; + + $this->request('GET', '/'); // warm cache + sleep(25); + $this->request('GET', '/'); // hit backend error + + $this->assertEquals(200, $this->response->getStatusCode()); + $this->assertEquals('OK', $this->response->getContent()); + $this->assertTraceContains('stale-if-error'); + } } class TestKernel implements HttpKernelInterface From 1edecf77c115fc1a5e7163ad1a829ed271d1ca9c Mon Sep 17 00:00:00 2001 From: Ivan Grigoriev Date: Fri, 31 Jan 2020 00:43:04 +0300 Subject: [PATCH 11/65] [Validator] fix access to uninitialized property when getting value --- .../Validator/Mapping/PropertyMetadata.php | 8 +++++++- .../Validator/Tests/Fixtures/Entity_74.php | 8 ++++++++ .../Tests/Mapping/PropertyMetadataTest.php | 13 +++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/Entity_74.php diff --git a/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php b/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php index b03a059f84350..872bd067be2be 100644 --- a/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php @@ -48,7 +48,13 @@ public function __construct($class, $name) */ public function getPropertyValue($object) { - return $this->getReflectionMember($object)->getValue($object); + $reflProperty = $this->getReflectionMember($object); + + if (\PHP_VERSION_ID >= 70400 && !$reflProperty->isInitialized($object)) { + return null; + } + + return $reflProperty->getValue($object); } /** diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Entity_74.php b/src/Symfony/Component/Validator/Tests/Fixtures/Entity_74.php new file mode 100644 index 0000000000000..cb22fb7f72410 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Entity_74.php @@ -0,0 +1,8 @@ +expectException('Symfony\Component\Validator\Exception\ValidatorException'); $metadata->getPropertyValue($entity); } + + /** + * @requires PHP 7.4 + */ + public function testGetPropertyValueFromUninitializedProperty() + { + $entity = new Entity_74(); + $metadata = new PropertyMetadata(self::CLASSNAME_74, 'uninitialized'); + + $this->assertNull($metadata->getPropertyValue($entity)); + } } From b2339b5e325aceffdda0c469b027b33ed43a28a1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 31 Jan 2020 10:55:33 +0100 Subject: [PATCH 12/65] Bump phpunit-bridge cache --- phpunit | 2 +- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpunit b/phpunit index 200a9c28b4c34..c89d2e400b602 100755 --- a/phpunit +++ b/phpunit @@ -1,7 +1,7 @@ #!/usr/bin/env php Date: Sat, 1 Feb 2020 11:00:56 +0100 Subject: [PATCH 13/65] Update PR template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0d234d8fe9b7f..57c15178547d8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ | Q | A | ------------- | --- -| Branch? | master for features / 3.4, 4.3, 4.4 or 5.0 for bug fixes +| Branch? | master for features / 3.4, 4.4 or 5.0 for bug fixes | Bug fix? | yes/no | New feature? | yes/no | Deprecations? | yes/no From e94c3fb87d699cf4a368a1757e0dc5570bfd8e4d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 2 Feb 2020 13:11:51 +0100 Subject: [PATCH 14/65] [Config] dont catch instances of Error --- .../Config/Resource/ClassExistenceResource.php | 2 ++ .../Component/Config/Tests/Fixtures/ParseError.php | 7 +++++++ .../Tests/Resource/ClassExistenceResourceTest.php | 12 ++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 src/Symfony/Component/Config/Tests/Fixtures/ParseError.php diff --git a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php index 685da72850e55..fc0259f418922 100644 --- a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php +++ b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php @@ -92,6 +92,8 @@ public function isFresh($timestamp) } } catch (\Throwable $e) { $exists[1] = $e->getMessage(); + + throw $e; } finally { self::$autoloadedClass = $autoloadedClass; if (!--self::$autoloadLevel) { diff --git a/src/Symfony/Component/Config/Tests/Fixtures/ParseError.php b/src/Symfony/Component/Config/Tests/Fixtures/ParseError.php new file mode 100644 index 0000000000000..6bb2213824830 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Fixtures/ParseError.php @@ -0,0 +1,7 @@ +assertFalse($res->isFresh(0)); } + + /** + * @requires PHP 7 + */ + public function testParseError() + { + $this->expectException('ParseError'); + + $res = new ClassExistenceResource(ParseError::class, false); + $res->isFresh(0); + } } From 6b02362c5b9e1e49cf934aef2d954c1e7d91452a Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 28 Jan 2020 01:09:27 +0100 Subject: [PATCH 15/65] [Phpunit] Fix running skipped tests expecting only deprecations --- .../Legacy/SymfonyTestsListenerTrait.php | 4 +++ .../OnlyExpectingDeprecationSkippedTest.php | 34 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 54c15b67ceedf..69bbcfc09eab0 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -222,6 +222,10 @@ public function startTest($test) } } + if (!$test->getTestResultObject()) { + return; + } + $annotations = $Test::parseTestMethodAnnotations(\get_class($test), $test->getName(false)); if (isset($annotations['class']['expectedDeprecation'])) { diff --git a/src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php b/src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php new file mode 100644 index 0000000000000..593e0b4e14342 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/OnlyExpectingDeprecationSkippedTest.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Tests; + +use PHPUnit\Framework\TestCase; + +/** + * This test is meant to be skipped. + * + * @requires extension ext-dummy + */ +final class OnlyExpectingDeprecationSkippedTest extends TestCase +{ + /** + * Do not remove this test in the next major versions. + * + * @group legacy + * + * @expectedDeprecation unreachable + */ + public function testExpectingOnlyDeprecations() + { + $this->fail('should never be ran.'); + } +} From 427bc3aa18dc67f0f952ee70dcca362c48463b98 Mon Sep 17 00:00:00 2001 From: Alessandro Chitolina Date: Fri, 31 Jan 2020 18:44:35 +0100 Subject: [PATCH 16/65] [Validator] try to call __get method if property is uninitialized --- .../Validator/Mapping/PropertyMetadata.php | 17 +++++++++++++++-- .../Tests/Fixtures/Entity_74_Proxy.php | 18 ++++++++++++++++++ .../Tests/Mapping/PropertyMetadataTest.php | 15 +++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/Entity_74_Proxy.php diff --git a/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php b/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php index 872bd067be2be..1adad95b80958 100644 --- a/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php @@ -50,8 +50,21 @@ public function getPropertyValue($object) { $reflProperty = $this->getReflectionMember($object); - if (\PHP_VERSION_ID >= 70400 && !$reflProperty->isInitialized($object)) { - return null; + if (\PHP_VERSION_ID >= 70400 && $reflProperty->hasType() && !$reflProperty->isInitialized($object)) { + // There is no way to check if a property has been unset or if it is uninitialized. + // When trying to access an uninitialized property, __get method is triggered. + + // If __get method is not present, no fallback is possible + // Otherwise we need to catch an Error in case we are trying to access an uninitialized but set property. + if (!method_exists($object, '__get')) { + return null; + } + + try { + return $reflProperty->getValue($object); + } catch (\Error $e) { + return null; + } } return $reflProperty->getValue($object); diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/Entity_74_Proxy.php b/src/Symfony/Component/Validator/Tests/Fixtures/Entity_74_Proxy.php new file mode 100644 index 0000000000000..d74badc7d7f96 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/Entity_74_Proxy.php @@ -0,0 +1,18 @@ +uninitialized); + } + + public function __get($name) + { + return 42; + } +} diff --git a/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php index 8d9e67881a9dc..8868ec64aac9f 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/PropertyMetadataTest.php @@ -15,11 +15,13 @@ use Symfony\Component\Validator\Mapping\PropertyMetadata; use Symfony\Component\Validator\Tests\Fixtures\Entity; use Symfony\Component\Validator\Tests\Fixtures\Entity_74; +use Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy; class PropertyMetadataTest extends TestCase { const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; const CLASSNAME_74 = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74'; + const CLASSNAME_74_PROXY = 'Symfony\Component\Validator\Tests\Fixtures\Entity_74_Proxy'; const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; public function testInvalidPropertyName() @@ -66,4 +68,17 @@ public function testGetPropertyValueFromUninitializedProperty() $this->assertNull($metadata->getPropertyValue($entity)); } + + /** + * @requires PHP 7.4 + */ + public function testGetPropertyValueFromUninitializedPropertyShouldNotReturnNullIfMagicGetIsPresent() + { + $entity = new Entity_74_Proxy(); + $metadata = new PropertyMetadata(self::CLASSNAME_74_PROXY, 'uninitialized'); + $notUnsetMetadata = new PropertyMetadata(self::CLASSNAME_74_PROXY, 'notUnset'); + + $this->assertNull($notUnsetMetadata->getPropertyValue($entity)); + $this->assertEquals(42, $metadata->getPropertyValue($entity)); + } } From b52b7b9fd643fff1d17c7204fc3ba55bb5ec8f55 Mon Sep 17 00:00:00 2001 From: Wouter de Jong Date: Sat, 1 Feb 2020 14:25:57 +0100 Subject: [PATCH 17/65] [Translation][Debug] Add installation and minimal example to README --- src/Symfony/Component/Debug/README.md | 14 +++++++++++++- src/Symfony/Component/Translation/README.md | 20 +++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Debug/README.md b/src/Symfony/Component/Debug/README.md index 38bc800c587b3..f0878df3fa38a 100644 --- a/src/Symfony/Component/Debug/README.md +++ b/src/Symfony/Component/Debug/README.md @@ -3,10 +3,22 @@ Debug Component The Debug component provides tools to ease debugging PHP code. +Getting Started +--------------- + +``` +$ composer install symfony/debug +``` + +```php +use Symfony\Component\Debug\Debug; + +Debug::enable(); +``` + Resources --------- - * [Documentation](https://symfony.com/doc/current/components/debug.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) diff --git a/src/Symfony/Component/Translation/README.md b/src/Symfony/Component/Translation/README.md index e80a70cad033e..f4f1706675d5a 100644 --- a/src/Symfony/Component/Translation/README.md +++ b/src/Symfony/Component/Translation/README.md @@ -3,10 +3,28 @@ Translation Component The Translation component provides tools to internationalize your application. +Getting Started +--------------- + +``` +$ composer require symfony/translation +``` + +```php +use Symfony\Component\Translation\Translator; + +$translator = new Translator('fr_FR'); +$translator->addResource('array', [ + 'Hello World!' => 'Bonjour !', +], 'fr_FR'); + +echo $translator->trans('Hello World!'); // outputs « Bonjour ! » +``` + Resources --------- - * [Documentation](https://symfony.com/doc/current/components/translation.html) + * [Documentation](https://symfony.com/doc/current/translation.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) From ce29631cd827634342ac5bd806c6809e6aed8d7e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Feb 2020 08:15:38 +0100 Subject: [PATCH 18/65] [Translation] Add missing use statement --- src/Symfony/Component/Translation/Command/XliffLintCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Translation/Command/XliffLintCommand.php b/src/Symfony/Component/Translation/Command/XliffLintCommand.php index 922e026c483c8..6b1976dc6b42f 100644 --- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php +++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Translation\Exception\InvalidArgumentException; /** * Validates XLIFF files syntax and outputs encountered errors. From a3e49f30c7fc5342cb27f7c378523059c2a2c2f4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Feb 2020 09:03:00 +0100 Subject: [PATCH 19/65] Fix CS --- .../MergeDoctrineCollectionListener.php | 2 +- src/Symfony/Bridge/Twig/Command/DebugCommand.php | 4 ++-- src/Symfony/Bridge/Twig/Command/LintCommand.php | 4 ++-- .../FrameworkExtensionTest.php | 2 +- .../Tests/Functional/AbstractWebTestCase.php | 2 +- .../Tests/Functional/AbstractWebTestCase.php | 2 +- .../Cache/Tests/Adapter/ApcuAdapterTest.php | 4 ++-- .../Component/Console/Command/Command.php | 4 ++-- .../Component/CssSelector/Node/AbstractNode.php | 2 +- .../DependencyInjection/Compiler/Compiler.php | 2 +- .../DependencyInjection/Compiler/PassConfig.php | 2 +- .../DependencyInjection/ContainerBuilder.php | 2 +- .../DependencyInjection/Extension/Extension.php | 4 ++-- .../Loader/Configurator/AbstractConfigurator.php | 2 +- .../ContainerAwareEventDispatcher.php | 2 +- .../Component/ExpressionLanguage/Node/Node.php | 4 ++-- src/Symfony/Component/Form/AbstractType.php | 2 +- .../Form/Extension/Core/Type/ChoiceType.php | 2 +- .../HttpFoundation/RedirectResponse.php | 2 +- .../Storage/Handler/AbstractSessionHandler.php | 2 +- .../Session/Storage/NativeSessionStorage.php | 8 ++++---- .../Session/Storage/Proxy/AbstractProxy.php | 2 +- src/Symfony/Component/HttpKernel/Kernel.php | 6 +++--- src/Symfony/Component/HttpKernel/Log/Logger.php | 2 +- .../ContainerControllerResolverTest.php | 2 +- .../DataCollector/RequestDataCollectorTest.php | 2 +- .../HttpKernel/Tests/Log/LoggerTest.php | 2 +- src/Symfony/Component/Intl/Collator/Collator.php | 6 +++--- .../Intl/NumberFormatter/NumberFormatter.php | 10 +++++----- .../Component/Lock/Store/CombinedStore.php | 2 +- .../Component/Lock/Store/MemcachedStore.php | 2 +- src/Symfony/Component/Lock/Store/RedisStore.php | 2 +- .../Component/Lock/Store/SemaphoreStore.php | 2 +- .../PipeStdinInStdoutStdErrStreamSelect.php | 10 +++++----- .../Component/Routing/Annotation/Route.php | 2 +- .../Routing/Loader/ObjectRouteLoader.php | 2 +- .../Core/Authentication/Token/AbstractToken.php | 2 +- .../Core/Encoder/Argon2iPasswordEncoder.php | 8 ++++---- .../Guard/AbstractGuardAuthenticator.php | 2 +- .../AbstractFormLoginAuthenticator.php | 4 ++-- .../Security/Http/Logout/LogoutUrlGenerator.php | 2 +- .../Component/Serializer/Annotation/Groups.php | 4 ++-- .../Component/Serializer/Annotation/MaxDepth.php | 4 ++-- .../Serializer/Normalizer/AbstractNormalizer.php | 4 ++-- src/Symfony/Component/Serializer/Serializer.php | 8 ++++---- src/Symfony/Component/Validator/Constraint.php | 16 ++++++++-------- .../Validator/Constraints/AbstractComparison.php | 6 +++--- .../Validator/Constraints/Composite.php | 6 +++--- src/Symfony/Component/VarDumper/Cloner/Stub.php | 2 +- 49 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php b/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php index aafbd1d3af03f..27be3afc5592e 100644 --- a/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php +++ b/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php @@ -73,7 +73,7 @@ public function onSubmit(FormEvent $event) */ public function onBind(FormEvent $event) { - if (__CLASS__ === \get_class($this)) { + if (__CLASS__ === static::class) { $this->bc = false; } else { // parent::onBind() has been called diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index b45b580ee4b46..17c62aaf3c607 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -104,10 +104,10 @@ protected function execute(InputInterface $input, OutputInterface $output) $decorated = $io->isDecorated(); // BC to be removed in 4.0 - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, 'getTwigEnvironment'); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', \get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', static::class.'::getTwigEnvironment'), E_USER_DEPRECATED); $this->twig = $this->getTwigEnvironment(); } diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index c8b5bb5ba2a05..dc47dd8cfb381 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -105,10 +105,10 @@ protected function execute(InputInterface $input, OutputInterface $output) $io = new SymfonyStyle($input, $output); // BC to be removed in 4.0 - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, 'getTwigEnvironment'); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', \get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', static::class.'::getTwigEnvironment'), E_USER_DEPRECATED); $this->twig = $this->getTwigEnvironment(); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 556fd9afd48e5..bdbb8ba4022b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -1141,7 +1141,7 @@ protected function createContainer(array $data = []) protected function createContainerFromFile($file, $data = [], $resetCompilerPasses = true, $compile = true) { - $cacheKey = md5(\get_class($this).$file.serialize($data)); + $cacheKey = md5(static::class.$file.serialize($data)); if ($compile && isset(self::$containerCache[$cacheKey])) { return self::$containerCache[$cacheKey]; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php index 03c6bdcbd7e11..eb0990ac81f6e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AbstractWebTestCase.php @@ -68,6 +68,6 @@ protected static function createKernel(array $options = []) protected static function getVarDir() { - return 'FB'.substr(strrchr(\get_called_class(), '\\'), 1); + return 'FB'.substr(strrchr(static::class, '\\'), 1); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php index 72a67a9a48763..280b3df71fa3a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AbstractWebTestCase.php @@ -68,6 +68,6 @@ protected static function createKernel(array $options = []) protected static function getVarDir() { - return 'SB'.substr(strrchr(\get_called_class(), '\\'), 1); + return 'SB'.substr(strrchr(static::class, '\\'), 1); } } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php index 5cca73f56189d..2f35ef0c7cdfd 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php @@ -54,7 +54,7 @@ public function testUnserializable() public function testVersion() { - $namespace = str_replace('\\', '.', \get_class($this)); + $namespace = str_replace('\\', '.', static::class); $pool1 = new ApcuAdapter($namespace, 0, 'p1'); @@ -79,7 +79,7 @@ public function testVersion() public function testNamespace() { - $namespace = str_replace('\\', '.', \get_class($this)); + $namespace = str_replace('\\', '.', static::class); $pool1 = new ApcuAdapter($namespace.'_1', 0, 'p1'); diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 493800b315d92..0574cb7388062 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -55,7 +55,7 @@ class Command */ public static function getDefaultName() { - $class = \get_called_class(); + $class = static::class; $r = new \ReflectionProperty($class, 'defaultName'); return $class === $r->class ? static::$defaultName : null; @@ -348,7 +348,7 @@ public function setDefinition($definition) public function getDefinition() { if (null === $this->definition) { - throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', \get_class($this))); + throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); } return $this->definition; diff --git a/src/Symfony/Component/CssSelector/Node/AbstractNode.php b/src/Symfony/Component/CssSelector/Node/AbstractNode.php index 1d5d8ff7ba1d8..de2e74aa88cab 100644 --- a/src/Symfony/Component/CssSelector/Node/AbstractNode.php +++ b/src/Symfony/Component/CssSelector/Node/AbstractNode.php @@ -34,7 +34,7 @@ abstract class AbstractNode implements NodeInterface public function getNodeName() { if (null === $this->nodeName) { - $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', \get_called_class()); + $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', static::class); } return $this->nodeName; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php index bf0d9c3eab058..c5f698b012b89 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php @@ -81,7 +81,7 @@ public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BE if (\func_num_args() >= 3) { $priority = func_get_arg(2); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index bf8d75e6df280..e470cdec2dc98 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -123,7 +123,7 @@ public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_O if (\func_num_args() >= 3) { $priority = func_get_arg(2); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index f9bfcb52109d5..c8250a71cfb76 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -474,7 +474,7 @@ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig: if (\func_num_args() >= 3) { $priority = func_get_arg(2); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Extension/Extension.php b/src/Symfony/Component/DependencyInjection/Extension/Extension.php index 8acb8ee31d48f..00fa9dc8da500 100644 --- a/src/Symfony/Component/DependencyInjection/Extension/Extension.php +++ b/src/Symfony/Component/DependencyInjection/Extension/Extension.php @@ -65,7 +65,7 @@ public function getNamespace() */ public function getAlias() { - $className = \get_class($this); + $className = static::class; if ('Extension' != substr($className, -9)) { throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); } @@ -79,7 +79,7 @@ public function getAlias() */ public function getConfiguration(array $config, ContainerBuilder $container) { - $class = \get_class($this); + $class = static::class; if (false !== strpos($class, "\0")) { return null; // ignore anonymous classes diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php index f7222d0ed50e8..5b3e704c25106 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php @@ -31,7 +31,7 @@ public function __call($method, $args) return \call_user_func_array([$this, 'set'.$method], $args); } - throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', \get_class($this), $method)); + throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', static::class, $method)); } /** diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index 1b33e1cab3f4e..18f1b4f8c317b 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -42,7 +42,7 @@ public function __construct(ContainerInterface $container) { $this->container = $container; - $class = \get_class($this); + $class = static::class; if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) { $class = get_parent_class($class); } diff --git a/src/Symfony/Component/ExpressionLanguage/Node/Node.php b/src/Symfony/Component/ExpressionLanguage/Node/Node.php index 7923cb1d64e4f..95045902be6e5 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/Node.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/Node.php @@ -40,7 +40,7 @@ public function __toString() $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); } - $repr = [str_replace('Symfony\Component\ExpressionLanguage\Node\\', '', \get_class($this)).'('.implode(', ', $attributes)]; + $repr = [str_replace('Symfony\Component\ExpressionLanguage\Node\\', '', static::class).'('.implode(', ', $attributes)]; if (\count($this->nodes)) { foreach ($this->nodes as $node) { @@ -76,7 +76,7 @@ public function evaluate($functions, $values) public function toArray() { - throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', \get_class($this))); + throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', static::class)); } public function dump() diff --git a/src/Symfony/Component/Form/AbstractType.php b/src/Symfony/Component/Form/AbstractType.php index 1a9cfd75be7f6..be3c87d9ca612 100644 --- a/src/Symfony/Component/Form/AbstractType.php +++ b/src/Symfony/Component/Form/AbstractType.php @@ -52,7 +52,7 @@ public function configureOptions(OptionsResolver $resolver) */ public function getBlockPrefix() { - return StringUtil::fqcnToBlockPrefix(\get_class($this)) ?: ''; + return StringUtil::fqcnToBlockPrefix(static::class) ?: ''; } /** diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index aec61a2b4d80a..2bfc87dd80fe3 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -273,7 +273,7 @@ public function configureOptions(OptionsResolver $resolver) // Set by the user if (true !== $choicesAsValues) { - throw new \RuntimeException(sprintf('The "choices_as_values" option of the %s should not be used. Remove it and flip the contents of the "choices" option instead.', \get_class($this))); + throw new \RuntimeException(sprintf('The "choices_as_values" option of the %s should not be used. Remove it and flip the contents of the "choices" option instead.', static::class)); } @trigger_error('The "choices_as_values" option is deprecated since Symfony 3.1 and will be removed in 4.0. You should not use it anymore.', E_USER_DEPRECATED); diff --git a/src/Symfony/Component/HttpFoundation/RedirectResponse.php b/src/Symfony/Component/HttpFoundation/RedirectResponse.php index a19efba3e3d5e..71ba9f8251f5c 100644 --- a/src/Symfony/Component/HttpFoundation/RedirectResponse.php +++ b/src/Symfony/Component/HttpFoundation/RedirectResponse.php @@ -42,7 +42,7 @@ public function __construct($url, $status = 302, $headers = []) throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); } - if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { + if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, CASE_LOWER))) { $this->headers->remove('cache-control'); } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php index eb09c0b54e01f..84ba0ebba3f79 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -133,7 +133,7 @@ public function destroy($sessionId) } if (!headers_sent() && filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN)) { if (!$this->sessionName) { - throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', \get_class($this))); + throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); } $sessionCookie = sprintf(' %s=', urlencode($this->sessionName)); $sessionCookieWithId = sprintf('%s%s;', $sessionCookie, urlencode($sessionId)); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index df7da3c72f046..cbf7cadc7e1f9 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -137,7 +137,7 @@ public function start() return true; } - if (\PHP_SESSION_ACTIVE === session_status()) { + if (PHP_SESSION_ACTIVE === session_status()) { throw new \RuntimeException('Failed to start the session: already started by PHP.'); } @@ -193,7 +193,7 @@ public function setName($name) public function regenerate($destroy = false, $lifetime = null) { // Cannot regenerate the session ID for non-active sessions. - if (\PHP_SESSION_ACTIVE !== session_status()) { + if (PHP_SESSION_ACTIVE !== session_status()) { return false; } @@ -341,7 +341,7 @@ public function isStarted() */ public function setOptions(array $options) { - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { + if (headers_sent() || PHP_SESSION_ACTIVE === session_status()) { return; } @@ -401,7 +401,7 @@ public function setSaveHandler($saveHandler = null) } $this->saveHandler = $saveHandler; - if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { + if (headers_sent() || PHP_SESSION_ACTIVE === session_status()) { return; } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php index 0303729e7b387..cd0635a1684d7 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php @@ -65,7 +65,7 @@ public function isWrapper() */ public function isActive() { - return \PHP_SESSION_ACTIVE === session_status(); + return PHP_SESSION_ACTIVE === session_status(); } /** diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 87f102a0fb26d..82930d8c27d2b 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -236,7 +236,7 @@ public function getBundle($name, $first = true/*, $noDeprecation = false */) } if (!isset($this->bundleMap[$name])) { - throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, \get_class($this))); + throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, static::class)); } if (true === $first) { @@ -583,7 +583,7 @@ protected function initializeContainer() $oldContainer = null; if ($fresh = $cache->isFresh()) { // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors - $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); + $errorLevel = error_reporting(E_ALL ^ E_WARNING); $fresh = $oldContainer = false; try { if (file_exists($cache->getPath()) && \is_object($this->container = include $cache->getPath())) { @@ -651,7 +651,7 @@ protected function initializeContainer() } if (null === $oldContainer && file_exists($cache->getPath())) { - $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); + $errorLevel = error_reporting(E_ALL ^ E_WARNING); try { $oldContainer = include $cache->getPath(); } catch (\Throwable $e) { diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php index 50cbcd428f933..f490293a62e03 100644 --- a/src/Symfony/Component/HttpKernel/Log/Logger.php +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -105,6 +105,6 @@ private function format($level, $message, array $context) $message = strtr($message, $replacements); } - return sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message).\PHP_EOL; + return sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message).PHP_EOL; } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php index bdb2a00f4be5a..97d21e95a44c8 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php @@ -39,7 +39,7 @@ public function testGetControllerService() $controller = $resolver->getController($request); - $this->assertInstanceOf(\get_class($this), $controller[0]); + $this->assertInstanceOf(static::class, $controller[0]); $this->assertSame('controllerMethod1', $controller[1]); } diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php index 9b6264be3920c..38979bba721d6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/RequestDataCollectorTest.php @@ -99,7 +99,7 @@ public function provideControllerCallables() '"Regular" callable', [$this, 'testControllerInspection'], [ - 'class' => RequestDataCollectorTest::class, + 'class' => self::class, 'method' => 'testControllerInspection', 'file' => __FILE__, 'line' => $r1->getStartLine(), diff --git a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php index 7439ae1376deb..79039c1c97555 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php @@ -186,7 +186,7 @@ public function testContextExceptionKeyCanBeExceptionOrOtherValues() public function testFormatter() { $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile, function ($level, $message, $context) { - return json_encode(['level' => $level, 'message' => $message, 'context' => $context]).\PHP_EOL; + return json_encode(['level' => $level, 'message' => $message, 'context' => $context]).PHP_EOL; }); $this->logger->error('An error', ['foo' => 'bar']); diff --git a/src/Symfony/Component/Intl/Collator/Collator.php b/src/Symfony/Component/Intl/Collator/Collator.php index a9557ec482618..d72fa77144730 100644 --- a/src/Symfony/Component/Intl/Collator/Collator.php +++ b/src/Symfony/Component/Intl/Collator/Collator.php @@ -109,9 +109,9 @@ public static function create($locale) public function asort(&$array, $sortFlag = self::SORT_REGULAR) { $intlToPlainFlagMap = [ - self::SORT_REGULAR => \SORT_REGULAR, - self::SORT_NUMERIC => \SORT_NUMERIC, - self::SORT_STRING => \SORT_STRING, + self::SORT_REGULAR => SORT_REGULAR, + self::SORT_NUMERIC => SORT_NUMERIC, + self::SORT_STRING => SORT_STRING, ]; $plainSortFlag = isset($intlToPlainFlagMap[$sortFlag]) ? $intlToPlainFlagMap[$sortFlag] : self::SORT_REGULAR; diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index e0426b364bd63..13bffbd45370d 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -201,9 +201,9 @@ class NumberFormatter * @see https://php.net/round */ private static $phpRoundingMap = [ - self::ROUND_HALFDOWN => \PHP_ROUND_HALF_DOWN, - self::ROUND_HALFEVEN => \PHP_ROUND_HALF_EVEN, - self::ROUND_HALFUP => \PHP_ROUND_HALF_UP, + self::ROUND_HALFDOWN => PHP_ROUND_HALF_DOWN, + self::ROUND_HALFEVEN => PHP_ROUND_HALF_EVEN, + self::ROUND_HALFUP => PHP_ROUND_HALF_UP, ]; /** @@ -357,7 +357,7 @@ public function format($value, $type = self::TYPE_DEFAULT) // The original NumberFormatter does not support this format type if (self::TYPE_CURRENCY === $type) { - trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); + trigger_error(__METHOD__.'(): Unsupported format type '.$type, E_USER_WARNING); return false; } @@ -513,7 +513,7 @@ public function parse($value, $type = self::TYPE_DOUBLE, &$position = 0) $type = (int) $type; if (self::TYPE_DEFAULT === $type || self::TYPE_CURRENCY === $type) { - trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); + trigger_error(__METHOD__.'(): Unsupported format type '.$type, E_USER_WARNING); return false; } diff --git a/src/Symfony/Component/Lock/Store/CombinedStore.php b/src/Symfony/Component/Lock/Store/CombinedStore.php index 241d39efcf096..d1ffaba653b89 100644 --- a/src/Symfony/Component/Lock/Store/CombinedStore.php +++ b/src/Symfony/Component/Lock/Store/CombinedStore.php @@ -93,7 +93,7 @@ public function save(Key $key) public function waitAndSave(Key $key) { - throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', \get_class($this))); + throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', static::class)); } /** diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php index d61bc6fa069a5..7ff893d58f153 100644 --- a/src/Symfony/Component/Lock/Store/MemcachedStore.php +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -70,7 +70,7 @@ public function save(Key $key) public function waitAndSave(Key $key) { - throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', \get_class($this))); + throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', static::class)); } /** diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index 4e328340260a2..56a91d7f062fb 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -73,7 +73,7 @@ public function save(Key $key) public function waitAndSave(Key $key) { - throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', \get_class($this))); + throw new NotSupportedException(sprintf('The store "%s" does not support blocking locks.', static::class)); } /** diff --git a/src/Symfony/Component/Lock/Store/SemaphoreStore.php b/src/Symfony/Component/Lock/Store/SemaphoreStore.php index 4ac15d6df11ba..fb72ff828d005 100644 --- a/src/Symfony/Component/Lock/Store/SemaphoreStore.php +++ b/src/Symfony/Component/Lock/Store/SemaphoreStore.php @@ -81,7 +81,7 @@ private function lock(Key $key, $blocking) if (\PHP_VERSION_ID >= 50601) { $acquired = @sem_acquire($resource, !$blocking); } elseif (!$blocking) { - throw new NotSupportedException(sprintf('The store "%s" does not supports non blocking locks.', \get_class($this))); + throw new NotSupportedException(sprintf('The store "%s" does not supports non blocking locks.', static::class)); } else { $acquired = @sem_acquire($resource); } diff --git a/src/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php b/src/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php index 9ea8981e19b7d..2e7716de7f4c7 100644 --- a/src/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php +++ b/src/Symfony/Component/Process/Tests/PipeStdinInStdoutStdErrStreamSelect.php @@ -29,15 +29,15 @@ $n = stream_select($r, $w, $e, 5); if (false === $n) { - die(ERR_SELECT_FAILED); + exit(ERR_SELECT_FAILED); } elseif ($n < 1) { - die(ERR_TIMEOUT); + exit(ERR_TIMEOUT); } if (in_array(STDOUT, $w) && strlen($out) > 0) { $written = fwrite(STDOUT, (string) $out, 32768); if (false === $written) { - die(ERR_WRITE_FAILED); + exit(ERR_WRITE_FAILED); } $out = (string) substr($out, $written); } @@ -48,7 +48,7 @@ if (in_array(STDERR, $w) && strlen($err) > 0) { $written = fwrite(STDERR, (string) $err, 32768); if (false === $written) { - die(ERR_WRITE_FAILED); + exit(ERR_WRITE_FAILED); } $err = (string) substr($err, $written); } @@ -65,7 +65,7 @@ if (false === $str || feof(STDIN)) { $read = null; if (!feof(STDIN)) { - die(ERR_READ_FAILED); + exit(ERR_READ_FAILED); } } } diff --git a/src/Symfony/Component/Routing/Annotation/Route.php b/src/Symfony/Component/Routing/Annotation/Route.php index 338ba512dfe47..42edbbcb22fe9 100644 --- a/src/Symfony/Component/Routing/Annotation/Route.php +++ b/src/Symfony/Component/Routing/Annotation/Route.php @@ -46,7 +46,7 @@ public function __construct(array $data) foreach ($data as $key => $value) { $method = 'set'.str_replace('_', '', $key); if (!method_exists($this, $method)) { - throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, \get_class($this))); + throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, static::class)); } $this->$method($value); } diff --git a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php index ce58dc7da44e2..b5fa1ccede546 100644 --- a/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php +++ b/src/Symfony/Component/Routing/Loader/ObjectRouteLoader.php @@ -55,7 +55,7 @@ public function load($resource, $type = null) $loaderObject = $this->getServiceObject($serviceString); if (!\is_object($loaderObject)) { - throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', \get_class($this), \gettype($loaderObject))); + throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', static::class, \gettype($loaderObject))); } if (!method_exists($loaderObject, $method)) { diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 83f85abda2a12..9d5a01d942ad4 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -216,7 +216,7 @@ public function setAttribute($name, $value) */ public function __toString() { - $class = \get_class($this); + $class = static::class; $class = substr($class, strrpos($class, '\\') + 1); $roles = []; diff --git a/src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php index 99738365ad4cf..e812cd25b1dcb 100644 --- a/src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php +++ b/src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php @@ -26,7 +26,7 @@ public static function isSupported() return true; } - return version_compare(\extension_loaded('sodium') ? \SODIUM_LIBRARY_VERSION : phpversion('libsodium'), '1.0.9', '>='); + return version_compare(\extension_loaded('sodium') ? SODIUM_LIBRARY_VERSION : phpversion('libsodium'), '1.0.9', '>='); } /** @@ -79,15 +79,15 @@ public function isPasswordValid($encoded, $raw, $salt) private function encodePasswordNative($raw) { - return password_hash($raw, \PASSWORD_ARGON2I); + return password_hash($raw, PASSWORD_ARGON2I); } private function encodePasswordSodiumFunction($raw) { $hash = sodium_crypto_pwhash_str( $raw, - \SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, - \SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE + SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE ); sodium_memzero($raw); diff --git a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php index 7bcfc39438dd9..f905b2f6b39b4 100644 --- a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php +++ b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php @@ -27,7 +27,7 @@ abstract class AbstractGuardAuthenticator implements AuthenticatorInterface */ public function supports(Request $request) { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0. Implement the "%s::supports()" method in class "%s" instead.', __METHOD__, AuthenticatorInterface::class, \get_class($this)), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0. Implement the "%s::supports()" method in class "%s" instead.', __METHOD__, AuthenticatorInterface::class, static::class), E_USER_DEPRECATED); return true; } diff --git a/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php b/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php index a9c565b6bb9b2..2c633b30a05e1 100644 --- a/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php +++ b/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php @@ -61,10 +61,10 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio */ public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) { - @trigger_error(sprintf('The AbstractFormLoginAuthenticator::onAuthenticationSuccess() implementation was deprecated in Symfony 3.1 and will be removed in Symfony 4.0. You should implement this method yourself in %s and remove getDefaultSuccessRedirectUrl().', \get_class($this)), E_USER_DEPRECATED); + @trigger_error(sprintf('The AbstractFormLoginAuthenticator::onAuthenticationSuccess() implementation was deprecated in Symfony 3.1 and will be removed in Symfony 4.0. You should implement this method yourself in %s and remove getDefaultSuccessRedirectUrl().', static::class), E_USER_DEPRECATED); if (!method_exists($this, 'getDefaultSuccessRedirectUrl')) { - throw new \Exception(sprintf('You must implement onAuthenticationSuccess() or getDefaultSuccessRedirectUrl() in %s.', \get_class($this))); + throw new \Exception(sprintf('You must implement onAuthenticationSuccess() or getDefaultSuccessRedirectUrl() in %s.', static::class)); } $targetPath = null; diff --git a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php index 71a071f3508a6..b00d34f90f9d5 100644 --- a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php +++ b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php @@ -52,7 +52,7 @@ public function registerListener($key, $logoutPath, $csrfTokenId, $csrfParameter if (\func_num_args() >= 6) { $context = func_get_arg(5); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('The "%s()" method will have a 6th `string $context = null` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/Serializer/Annotation/Groups.php b/src/Symfony/Component/Serializer/Annotation/Groups.php index 7a9b0bd2c1052..4358a3e26dcb9 100644 --- a/src/Symfony/Component/Serializer/Annotation/Groups.php +++ b/src/Symfony/Component/Serializer/Annotation/Groups.php @@ -34,13 +34,13 @@ class Groups public function __construct(array $data) { if (!isset($data['value']) || !$data['value']) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" cannot be empty.', \get_class($this))); + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" cannot be empty.', static::class)); } $value = (array) $data['value']; foreach ($value as $group) { if (!\is_string($group)) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a string or an array of strings.', \get_class($this))); + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a string or an array of strings.', static::class)); } } diff --git a/src/Symfony/Component/Serializer/Annotation/MaxDepth.php b/src/Symfony/Component/Serializer/Annotation/MaxDepth.php index a274c20d85283..9939fdab1cd18 100644 --- a/src/Symfony/Component/Serializer/Annotation/MaxDepth.php +++ b/src/Symfony/Component/Serializer/Annotation/MaxDepth.php @@ -31,11 +31,11 @@ class MaxDepth public function __construct(array $data) { if (!isset($data['value'])) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" should be set.', \get_class($this))); + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" should be set.', static::class)); } if (!\is_int($data['value']) || $data['value'] <= 0) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a positive integer.', \get_class($this))); + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a positive integer.', static::class)); } $this->maxDepth = $data['value']; diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index bf9afb701e45b..b2b4604e35a39 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -304,10 +304,10 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref if (\func_num_args() >= 6) { $format = func_get_arg(5); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s::%s() will have a 6th `string $format = null` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', \get_class($this), __FUNCTION__), E_USER_DEPRECATED); + @trigger_error(sprintf('Method %s::%s() will have a 6th `string $format = null` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', static::class, __FUNCTION__), E_USER_DEPRECATED); } } diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index a29a1482ddef8..0e2143e93a555 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -193,7 +193,7 @@ public function supportsNormalization($data, $format = null/*, array $context = if (\func_num_args() > 2) { $context = func_get_arg(2); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('The "%s()" method will have a third `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED); @@ -214,7 +214,7 @@ public function supportsDenormalization($data, $type, $format = null/*, array $c if (\func_num_args() > 3) { $context = func_get_arg(3); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('The "%s()" method will have a fourth `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED); @@ -292,7 +292,7 @@ public function supportsEncoding($format/*, array $context = []*/) if (\func_num_args() > 1) { $context = func_get_arg(1); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('The "%s()" method will have a second `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED); @@ -313,7 +313,7 @@ public function supportsDecoding($format/*, array $context = []*/) if (\func_num_args() > 1) { $context = func_get_arg(1); } else { - if (__CLASS__ !== \get_class($this)) { + if (__CLASS__ !== static::class) { $r = new \ReflectionMethod($this, __FUNCTION__); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { @trigger_error(sprintf('The "%s()" method will have a second `$context = []` argument in version 4.0. Not defining it is deprecated since Symfony 3.3.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index 349698eb1af59..693689b912c34 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -70,7 +70,7 @@ abstract class Constraint public static function getErrorName($errorCode) { if (!isset(static::$errorNames[$errorCode])) { - throw new InvalidArgumentException(sprintf('The error code "%s" does not exist for constraint of type "%s".', $errorCode, \get_called_class())); + throw new InvalidArgumentException(sprintf('The error code "%s" does not exist for constraint of type "%s".', $errorCode, static::class)); } return static::$errorNames[$errorCode]; @@ -115,7 +115,7 @@ public function __construct($options = null) if (\is_array($options) && isset($options['value']) && !property_exists($this, 'value')) { if (null === $defaultOption) { - throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint "%s".', \get_class($this))); + throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint "%s".', static::class)); } $options[$defaultOption] = $options['value']; @@ -136,7 +136,7 @@ public function __construct($options = null) } } elseif (null !== $options && !(\is_array($options) && 0 === \count($options))) { if (null === $defaultOption) { - throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint "%s".', \get_class($this))); + throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint "%s".', static::class)); } if (\array_key_exists($defaultOption, $knownOptions)) { @@ -148,11 +148,11 @@ public function __construct($options = null) } if (\count($invalidOptions) > 0) { - throw new InvalidOptionsException(sprintf('The options "%s" do not exist in constraint "%s".', implode('", "', $invalidOptions), \get_class($this)), $invalidOptions); + throw new InvalidOptionsException(sprintf('The options "%s" do not exist in constraint "%s".', implode('", "', $invalidOptions), static::class), $invalidOptions); } if (\count($missingOptions) > 0) { - throw new MissingOptionsException(sprintf('The options "%s" must be set for constraint "%s".', implode('", "', array_keys($missingOptions)), \get_class($this)), array_keys($missingOptions)); + throw new MissingOptionsException(sprintf('The options "%s" must be set for constraint "%s".', implode('", "', array_keys($missingOptions)), static::class), array_keys($missingOptions)); } } @@ -176,7 +176,7 @@ public function __set($option, $value) return; } - throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, \get_class($this)), [$option]); + throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, static::class), [$option]); } /** @@ -202,7 +202,7 @@ public function __get($option) return $this->groups; } - throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, \get_class($this)), [$option]); + throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, static::class), [$option]); } /** @@ -266,7 +266,7 @@ public function getRequiredOptions() */ public function validatedBy() { - return \get_class($this).'Validator'; + return static::class.'Validator'; } /** diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php index 89c2690c081cd..01c8be31cbf06 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php @@ -38,15 +38,15 @@ public function __construct($options = null) if (\is_array($options)) { if (!isset($options['value']) && !isset($options['propertyPath'])) { - throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires either the "value" or "propertyPath" option to be set.', \get_class($this))); + throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires either the "value" or "propertyPath" option to be set.', static::class)); } if (isset($options['value']) && isset($options['propertyPath'])) { - throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires only one of the "value" or "propertyPath" options to be set, not both.', \get_class($this))); + throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires only one of the "value" or "propertyPath" options to be set, not both.', static::class)); } if (isset($options['propertyPath']) && !class_exists(PropertyAccess::class)) { - throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires the Symfony PropertyAccess component to use the "propertyPath" option.', \get_class($this))); + throw new ConstraintDefinitionException(sprintf('The "%s" constraint requires the Symfony PropertyAccess component to use the "propertyPath" option.', static::class)); } } diff --git a/src/Symfony/Component/Validator/Constraints/Composite.php b/src/Symfony/Component/Validator/Constraints/Composite.php index 18ea5e319f7f1..9c423b0dc376a 100644 --- a/src/Symfony/Component/Validator/Constraints/Composite.php +++ b/src/Symfony/Component/Validator/Constraints/Composite.php @@ -71,11 +71,11 @@ public function __construct($options = null) $constraint = \get_class($constraint); } - throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, \get_class($this))); + throw new ConstraintDefinitionException(sprintf('The value %s is not an instance of Constraint in constraint %s', $constraint, static::class)); } if ($constraint instanceof Valid) { - throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', \get_class($this))); + throw new ConstraintDefinitionException(sprintf('The constraint Valid cannot be nested inside constraint %s. You can only declare the Valid constraint directly on a field or method.', static::class)); } } @@ -99,7 +99,7 @@ public function __construct($options = null) $excessGroups = array_diff($constraint->groups, $this->groups); if (\count($excessGroups) > 0) { - throw new ConstraintDefinitionException(sprintf('The group(s) "%s" passed to the constraint %s should also be passed to its containing constraint %s', implode('", "', $excessGroups), \get_class($constraint), \get_class($this))); + throw new ConstraintDefinitionException(sprintf('The group(s) "%s" passed to the constraint %s should also be passed to its containing constraint %s', implode('", "', $excessGroups), \get_class($constraint), static::class)); } } else { $constraint->groups = $this->groups; diff --git a/src/Symfony/Component/VarDumper/Cloner/Stub.php b/src/Symfony/Component/VarDumper/Cloner/Stub.php index 27dd3ef32c4df..a56120ce36311 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Stub.php +++ b/src/Symfony/Component/VarDumper/Cloner/Stub.php @@ -48,7 +48,7 @@ public function __sleep() { $properties = []; - if (!isset(self::$defaultProperties[$c = \get_class($this)])) { + if (!isset(self::$defaultProperties[$c = static::class])) { self::$defaultProperties[$c] = get_class_vars($c); foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) { From c2e0aab7bee49e896aaad62871a0389fd4d34d06 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 4 Feb 2020 10:59:34 +0100 Subject: [PATCH 20/65] cs fix --- .../FrameworkBundle/Tests/Translation/TranslatorTest.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index e38e11601b66e..9cb6046fa9631 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -16,6 +16,7 @@ use Symfony\Bundle\FrameworkBundle\Translation\Translator; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Translation\Formatter\MessageFormatter; +use Symfony\Component\Translation\Loader\YamlFileLoader; use Symfony\Component\Translation\MessageCatalogue; class TranslatorTest extends TestCase @@ -123,7 +124,7 @@ public function testTransWithCachingWithInvalidLocaleOmittingLocale() */ public function testLoadResourcesWithoutCachingOmittingLocale() { - $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); + $loader = new YamlFileLoader(); $resourceFiles = [ 'fr' => [ __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', @@ -171,7 +172,7 @@ public function testGetDefaultLocaleOmittingLocaleWithPsrContainer() */ public function testWarmupOmittingLocale() { - $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); + $loader = new YamlFileLoader(); $resourceFiles = [ 'fr' => [ __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', @@ -259,7 +260,7 @@ public function testTransWithCachingWithInvalidLocale() public function testLoadResourcesWithoutCaching() { - $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); + $loader = new YamlFileLoader(); $resourceFiles = [ 'fr' => [ __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', @@ -436,7 +437,7 @@ public function getTranslator($loader, $options = [], $loaderFomat = 'loader', $ public function testWarmup() { - $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); + $loader = new YamlFileLoader(); $resourceFiles = [ 'fr' => [ __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', From 73bc793be2bb58c936b3df34507ef7d8320abc72 Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Wed, 5 Feb 2020 17:32:02 +0100 Subject: [PATCH 21/65] Replace 403 with 401 in onAuthenticationFailure method --- .../Component/Security/Guard/GuardAuthenticatorInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php index 7372eb844a6d0..5701157e1cfa3 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php @@ -107,7 +107,7 @@ public function createAuthenticatedToken(UserInterface $user, $providerKey); * Called when authentication executed, but failed (e.g. wrong username password). * * This should return the Response sent back to the user, like a - * RedirectResponse to the login page or a 403 response. + * RedirectResponse to the login page or a 401 response. * * If you return null, the request will continue, but the user will * not be authenticated. This is probably not what you want to do. From 9bb194098f6df090f4174096c1e9a86a903f9b87 Mon Sep 17 00:00:00 2001 From: Jules Pietri Date: Wed, 5 Feb 2020 19:53:27 +0100 Subject: [PATCH 22/65] [DoctrineBridge] Fixed submitting ids with query limit or offset --- .../Form/ChoiceList/ORMQueryBuilderLoader.php | 2 +- .../Tests/Form/Type/EntityTypeTest.php | 27 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index 875b08dae95e0..9c1f779e5fcad 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -62,7 +62,7 @@ public function getEntitiesByIds($identifier, array $values) $metadata = $this->queryBuilder->getEntityManager()->getClassMetadata(current($this->queryBuilder->getRootEntities())); foreach ($this->getEntities() as $entity) { - if (\in_array(current($metadata->getIdentifierValues($entity)), $values, true)) { + if (\in_array((string) current($metadata->getIdentifierValues($entity)), $values, true)) { $choices[] = $entity; } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index bc12de5d427e9..7bb57d707ddd8 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -956,7 +956,32 @@ public function testDisallowChoicesThatAreNotIncludedQueryBuilderSingleIdentifie $this->assertNull($field->getData()); } - public function testDisallowChoicesThatAreNotIncludedQueryBuilderSingleIdentifierWithLimit() + public function testSingleIdentifierWithLimit() + { + $entity1 = new SingleIntIdEntity(1, 'Foo'); + $entity2 = new SingleIntIdEntity(2, 'Bar'); + $entity3 = new SingleIntIdEntity(3, 'Baz'); + + $this->persist([$entity1, $entity2, $entity3]); + + $repository = $this->em->getRepository(self::SINGLE_IDENT_CLASS); + + $field = $this->factory->createNamed('name', static::TESTED_TYPE, null, [ + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + 'query_builder' => $repository->createQueryBuilder('e') + ->where('e.id IN (1, 2, 3)') + ->setMaxResults(1), + 'choice_label' => 'name', + ]); + + $field->submit('1'); + + $this->assertTrue($field->isSynchronized()); + $this->assertSame($entity1, $field->getData()); + } + + public function testDisallowChoicesThatAreNotIncludedByQueryBuilderSingleIdentifierWithLimit() { $entity1 = new SingleIntIdEntity(1, 'Foo'); $entity2 = new SingleIntIdEntity(2, 'Bar'); From f46e6cb8a086d0c44502cf35e699a1aa0044b11c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Sep 2018 10:27:39 +0200 Subject: [PATCH 23/65] [HttpFoundation][FrameworkBundle] fix support for samesite in session cookies --- .../DependencyInjection/Configuration.php | 2 + .../FrameworkExtension.php | 2 +- .../DependencyInjection/ConfigurationTest.php | 1 + .../HttpFoundation/Session/SessionUtils.php | 59 +++++++++++++++++++ .../Handler/AbstractSessionHandler.php | 50 +++++++--------- .../Session/Storage/NativeSessionStorage.php | 42 +++++++++++-- .../Storage/Handler/Fixtures/storage.expected | 3 +- .../Fixtures/with_cookie_and_session.expected | 1 + .../Handler/Fixtures/with_samesite.expected | 16 +++++ .../Handler/Fixtures/with_samesite.php | 13 ++++ .../with_samesite_and_migration.expected | 23 ++++++++ .../Fixtures/with_samesite_and_migration.php | 15 +++++ .../Storage/NativeSessionStorageTest.php | 8 ++- 13 files changed, 196 insertions(+), 39 deletions(-) create mode 100644 src/Symfony/Component/HttpFoundation/Session/SessionUtils.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 00316daf55666..67ddeb2f8b2ee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -20,6 +20,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\Form\Form; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\Lock\Lock; use Symfony\Component\Lock\Store\SemaphoreStore; use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; @@ -490,6 +491,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode) ->scalarNode('cookie_domain')->end() ->booleanNode('cookie_secure')->end() ->booleanNode('cookie_httponly')->defaultTrue()->end() + ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT])->defaultNull()->end() ->booleanNode('use_cookies')->end() ->scalarNode('gc_divisor')->end() ->scalarNode('gc_probability')->defaultValue(1)->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 3e28e52ad3d0a..1762112a490f0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -867,7 +867,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c // session storage $container->setAlias('session.storage', $config['storage_id'])->setPrivate(true); $options = ['cache_limiter' => '0']; - foreach (['name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'use_strict_mode'] as $key) { + foreach (['name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'cookie_samesite', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor'] as $key) { if (isset($config[$key])) { $options[$key] = $config[$key]; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index e66c9ebfc610f..dbfd38f34d4d5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -436,6 +436,7 @@ protected static function getBundleDefaultConfig() 'storage_id' => 'session.storage.native', 'handler_id' => 'session.handler.native_file', 'cookie_httponly' => true, + 'cookie_samesite' => null, 'gc_probability' => 1, 'save_path' => '%kernel.cache_dir%/sessions', 'metadata_update_threshold' => '0', diff --git a/src/Symfony/Component/HttpFoundation/Session/SessionUtils.php b/src/Symfony/Component/HttpFoundation/Session/SessionUtils.php new file mode 100644 index 0000000000000..04a25f7165e4a --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/SessionUtils.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +/** + * Session utility functions. + * + * @author Nicolas Grekas + * @author Rémon van de Kamp + * + * @internal + */ +final class SessionUtils +{ + /** + * Find the session header amongst the headers that are to be sent, remove it, and return + * it so the caller can process it further. + */ + public static function popSessionCookie($sessionName, $sessionId) + { + $sessionCookie = null; + $sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName)); + $sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); + $otherCookies = []; + foreach (headers_list() as $h) { + if (0 !== stripos($h, 'Set-Cookie:')) { + continue; + } + if (11 === strpos($h, $sessionCookiePrefix, 11)) { + $sessionCookie = $h; + + if (11 !== strpos($h, $sessionCookieWithId, 11)) { + $otherCookies[] = $h; + } + } else { + $otherCookies[] = $h; + } + } + if (null === $sessionCookie) { + return null; + } + + header_remove('Set-Cookie'); + foreach ($otherCookies as $h) { + header($h, false); + } + + return $sessionCookie; + } +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php index 84ba0ebba3f79..ec59d895ce3a3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; +use Symfony\Component\HttpFoundation\Session\SessionUtils; + /** * This abstract session handler provides a generic implementation * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, @@ -27,7 +29,7 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess private $igbinaryEmptyData; /** - * {@inheritdoc} + * @return bool */ public function open($savePath, $sessionName) { @@ -62,7 +64,7 @@ abstract protected function doWrite($sessionId, $data); abstract protected function doDestroy($sessionId); /** - * {@inheritdoc} + * @return bool */ public function validateId($sessionId) { @@ -73,7 +75,7 @@ public function validateId($sessionId) } /** - * {@inheritdoc} + * @return string */ public function read($sessionId) { @@ -99,7 +101,7 @@ public function read($sessionId) } /** - * {@inheritdoc} + * @return bool */ public function write($sessionId, $data) { @@ -124,7 +126,7 @@ public function write($sessionId, $data) } /** - * {@inheritdoc} + * @return bool */ public function destroy($sessionId) { @@ -135,31 +137,23 @@ public function destroy($sessionId) if (!$this->sessionName) { throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); } - $sessionCookie = sprintf(' %s=', urlencode($this->sessionName)); - $sessionCookieWithId = sprintf('%s%s;', $sessionCookie, urlencode($sessionId)); - $sessionCookieFound = false; - $otherCookies = []; - foreach (headers_list() as $h) { - if (0 !== stripos($h, 'Set-Cookie:')) { - continue; - } - if (11 === strpos($h, $sessionCookie, 11)) { - $sessionCookieFound = true; - - if (11 !== strpos($h, $sessionCookieWithId, 11)) { - $otherCookies[] = $h; - } + $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); + + /* + * We send an invalidation Set-Cookie header (zero lifetime) + * when either the session was started or a cookie with + * the session name was sent by the client (in which case + * we know it's invalid as a valid session cookie would've + * started the session). + */ + if (null === $cookie || isset($_COOKIE[$this->sessionName])) { + if (\PHP_VERSION_ID < 70300) { + setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), FILTER_VALIDATE_BOOLEAN)); } else { - $otherCookies[] = $h; - } - } - if ($sessionCookieFound) { - header_remove('Set-Cookie'); - foreach ($otherCookies as $h) { - header($h, false); + $params = session_get_cookie_params(); + unset($params['lifetime']); + setcookie($this->sessionName, '', $params); } - } else { - setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), FILTER_VALIDATE_BOOLEAN)); } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index cbf7cadc7e1f9..7502897a4456b 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\SessionUtils; use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; @@ -48,6 +49,11 @@ class NativeSessionStorage implements SessionStorageInterface */ protected $metadataBag; + /** + * @var string|null + */ + private $emulateSameSite; + /** * Depending on how you want the storage driver to behave you probably * want to override this constructor entirely. @@ -67,6 +73,7 @@ class NativeSessionStorage implements SessionStorageInterface * cookie_lifetime, "0" * cookie_path, "/" * cookie_secure, "" + * cookie_samesite, null * entropy_file, "" * entropy_length, "0" * gc_divisor, "100" @@ -94,9 +101,7 @@ class NativeSessionStorage implements SessionStorageInterface * trans_sid_hosts, $_SERVER['HTTP_HOST'] * trans_sid_tags, "a=href,area=href,frame=src,form=" * - * @param array $options Session configuration options - * @param \SessionHandlerInterface|null $handler - * @param MetadataBag $metaBag MetadataBag + * @param AbstractProxy|\SessionHandlerInterface|null $handler */ public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null) { @@ -150,6 +155,13 @@ public function start() throw new \RuntimeException('Failed to start the session'); } + if (null !== $this->emulateSameSite) { + $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); + if (null !== $originalCookie) { + header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); + } + } + $this->loadSession(); return true; @@ -215,6 +227,13 @@ public function regenerate($destroy = false, $lifetime = null) // @see https://bugs.php.net/70013 $this->loadSession(); + if (null !== $this->emulateSameSite) { + $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); + if (null !== $originalCookie) { + header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); + } + } + return $isRegenerated; } @@ -223,6 +242,7 @@ public function regenerate($destroy = false, $lifetime = null) */ public function save() { + // Store a copy so we can restore the bags in case the session was not left empty $session = $_SESSION; foreach ($this->bags as $bag) { @@ -248,7 +268,11 @@ public function save() session_write_close(); } finally { restore_error_handler(); - $_SESSION = $session; + + // Restore only if not empty + if ($_SESSION) { + $_SESSION = $session; + } } $this->closed = true; @@ -347,7 +371,7 @@ public function setOptions(array $options) $validOptions = array_flip([ 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', + 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', 'hash_function', 'lazy_write', 'name', 'referer_check', @@ -360,6 +384,12 @@ public function setOptions(array $options) foreach ($options as $key => $value) { if (isset($validOptions[$key])) { + if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) { + // PHP < 7.3 does not support same_site cookies. We will emulate it in + // the start() method instead. + $this->emulateSameSite = $value; + continue; + } ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); } } @@ -381,7 +411,7 @@ public function setOptions(array $options) * @see https://php.net/sessionhandlerinterface * @see https://php.net/sessionhandler * - * @param \SessionHandlerInterface|null $saveHandler + * @param AbstractProxy|\SessionHandlerInterface|null $saveHandler * * @throws \InvalidArgumentException */ diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.expected b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.expected index 4533a10a1f7cf..05a5d5d0b090f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.expected +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.expected @@ -11,10 +11,11 @@ $_SESSION is not empty write destroy close -$_SESSION is not empty +$_SESSION is empty Array ( [0] => Content-Type: text/plain; charset=utf-8 [1] => Cache-Control: max-age=0, private, must-revalidate + [2] => Set-Cookie: sid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; secure; HttpOnly ) shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected index 5de2d9e3904ed..63078228df139 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected @@ -20,5 +20,6 @@ Array [0] => Content-Type: text/plain; charset=utf-8 [1] => Cache-Control: max-age=10800, private, must-revalidate [2] => Set-Cookie: abc=def + [3] => Set-Cookie: sid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; secure; HttpOnly ) shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected new file mode 100644 index 0000000000000..d20fb88ec052f --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected @@ -0,0 +1,16 @@ +open +validateId +read +doRead: +read + +write +doWrite: foo|s:3:"bar"; +close +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: max-age=0, private, must-revalidate + [2] => Set-Cookie: sid=random_session_id; path=/; secure; HttpOnly; SameSite=lax +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php new file mode 100644 index 0000000000000..fc2c4182895ac --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php @@ -0,0 +1,13 @@ + 'lax']); +$storage->setSaveHandler(new TestSessionHandler()); +$storage->start(); + +$_SESSION = ['foo' => 'bar']; + +ob_start(function ($buffer) { return str_replace(session_id(), 'random_session_id', $buffer); }); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.expected b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.expected new file mode 100644 index 0000000000000..8b5fc08bd375b --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.expected @@ -0,0 +1,23 @@ +open +validateId +read +doRead: +read +destroy +close +open +validateId +read +doRead: +read + +write +doWrite: foo|s:3:"bar"; +close +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: max-age=0, private, must-revalidate + [2] => Set-Cookie: sid=random_session_id; path=/; secure; HttpOnly; SameSite=lax +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.php new file mode 100644 index 0000000000000..a28b6fedfc375 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.php @@ -0,0 +1,15 @@ + 'lax']); +$storage->setSaveHandler(new TestSessionHandler()); +$storage->start(); + +$_SESSION = ['foo' => 'bar']; + +$storage->regenerate(true); + +ob_start(function ($buffer) { return preg_replace('~_sf2_meta.*$~m', '', str_replace(session_id(), 'random_session_id', $buffer)); }); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 9ce8108dacc61..d2cf324525443 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -36,7 +36,7 @@ class NativeSessionStorageTest extends TestCase protected function setUp() { $this->iniSet('session.save_handler', 'files'); - $this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test'); + $this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sftest'); if (!is_dir($this->savePath)) { mkdir($this->savePath); } @@ -167,6 +167,10 @@ public function testCookieOptions() 'cookie_httponly' => false, ]; + if (\PHP_VERSION_ID >= 70300) { + $options['cookie_samesite'] = 'lax'; + } + $this->getStorage($options); $temp = session_get_cookie_params(); $gco = []; @@ -175,8 +179,6 @@ public function testCookieOptions() $gco['cookie_'.$key] = $value; } - unset($gco['cookie_samesite']); - $this->assertEquals($options, $gco); } From 3604bb701885fb5330175c96b91522420a7e0496 Mon Sep 17 00:00:00 2001 From: Wim Molenberghs Date: Fri, 7 Feb 2020 07:50:31 +0100 Subject: [PATCH 24/65] Update UserPasswordEncoderCommand.php --- .../SecurityBundle/Command/UserPasswordEncoderCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index a5537eca5d208..3f33624432f65 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -87,16 +87,16 @@ protected function configure() Pass the full user class path as the second argument to encode passwords for your own entities: - php %command.full_name% --no-interaction [password] App\Entity\User + php %command.full_name% --no-interaction [password] 'App\Entity\User' Executing the command interactively allows you to generate a random salt for encoding the password: - php %command.full_name% [password] App\Entity\User + php %command.full_name% [password] 'App\Entity\User' In case your encoder doesn't require a salt, add the empty-salt option: - php %command.full_name% --empty-salt [password] App\Entity\User + php %command.full_name% --empty-salt [password] 'App\Entity\User' EOF ) From abac71b0a44bfb11c60e21a3f50f0ca3c16021d2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 7 Feb 2020 09:43:36 +0100 Subject: [PATCH 25/65] [FrameworkBundle] fix "samesite" in XSD --- .../DependencyInjection/Configuration.php | 2 +- .../Resources/config/schema/symfony-1.0.xsd | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 67ddeb2f8b2ee..400c8a7920b8f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -491,7 +491,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode) ->scalarNode('cookie_domain')->end() ->booleanNode('cookie_secure')->end() ->booleanNode('cookie_httponly')->defaultTrue()->end() - ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT])->defaultNull()->end() + ->enumNode('cookie_samesite')->values([null, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT, Cookie::SAMESITE_NONE])->defaultNull()->end() ->booleanNode('use_cookies')->end() ->scalarNode('gc_divisor')->end() ->scalarNode('gc_probability')->defaultValue(1)->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 531f7dddb970f..39011822e99e9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -113,6 +113,7 @@ + @@ -306,6 +307,15 @@ + + + + + + + + + From 02e5d73116daa77164e84dfaaa44b77f9a3bf774 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 7 Feb 2020 10:11:45 +0100 Subject: [PATCH 26/65] [FrameworkBundle] fix deps=low --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index dae941c1f780e..020e4f1b475eb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -24,7 +24,7 @@ "symfony/config": "^3.4.31|^4.3.4", "symfony/debug": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/http-foundation": "^3.4.13|~4.3", + "symfony/http-foundation": "^3.4.37|^4.4.5", "symfony/http-kernel": "^3.4.31|^4.3.4", "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "~2.8|~3.0|~4.0", From 16dd360511ceadf81d90d30db2cd29e73bab5b00 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 7 Feb 2020 10:12:20 +0100 Subject: [PATCH 27/65] [FrameworkBundle] fix fix deps=low --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 020e4f1b475eb..0cfc665551844 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -24,7 +24,7 @@ "symfony/config": "^3.4.31|^4.3.4", "symfony/debug": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/http-foundation": "^3.4.37|^4.4.5", + "symfony/http-foundation": "^3.4.38|^4.4.5", "symfony/http-kernel": "^3.4.31|^4.3.4", "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "~2.8|~3.0|~4.0", From 47f467a4cc56ae0490284591e230e067878d0489 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 7 Feb 2020 10:13:59 +0100 Subject: [PATCH 28/65] [FrameworkBundle] fix fix fix deps=low --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 0cfc665551844..aad4e3fc612f0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -24,7 +24,7 @@ "symfony/config": "^3.4.31|^4.3.4", "symfony/debug": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", - "symfony/http-foundation": "^3.4.38|^4.4.5", + "symfony/http-foundation": "^3.4.38|^4.3", "symfony/http-kernel": "^3.4.31|^4.3.4", "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "~2.8|~3.0|~4.0", From 365f4d76bd4b22091489d9607ecdcb766d959a9b Mon Sep 17 00:00:00 2001 From: Erkhembayar Gantulga Date: Sat, 8 Feb 2020 18:05:56 +0800 Subject: [PATCH 29/65] [Validator] Added the missing Mongolian translations https://github.com/symfony/symfony/issues/30175 Added the missing translations for the Mongolian ("mn") locale. --- .../Resources/translations/validators.mn.xlf | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf index 4be2198aa3b27..b1458eee1ac0b 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.mn.xlf @@ -146,6 +146,226 @@ This value is not a valid language. Энэ утга үнэн зөв хэл биш байна . + + This value is not a valid country. + Энэ утга үнэн бодит улс биш байна. + + + This value is already used. + Энэ утга аль хэдийнээ хэрэглэгдсэн байна. + + + The size of the image could not be detected. + Зургийн хэмжээ тогтоогдож чадсангүй. + + + The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. + Зургийн өргөн хэтэрхий том байна ({{ width }}px). Өргөн нь хамгийн ихдээ {{ max_width }}px байх боломжтой. + + + The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. + Зургийн өргөн хэтэрхий жижиг байна ({{ width }}px). Өргөн нь хамгийн багадаа {{ min_width }}px байх боломжтой. + + + The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. + Зургийн өндөр хэтэрхий том байна ({{ height }}px). Өндөр нь хамгийн ихдээ {{ max_height }}px байх боломжтой. + + + The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. + Зургийн өндөр хэтэрхий жижиг байна ({{ height }}px). Өндөр нь хамгийн багадаа {{ min_height }}px байх боломжтой. + + + This value should be the user's current password. + Энэ утга хэрэглэгчийн одоогийн нууц үг байх ёстой. + + + This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. + Энэ утга яг {{ limit }} тэмдэгт байх ёстой.|Энэ утга яг {{ limit }} тэмдэгт байх ёстой. + + + The file was only partially uploaded. + Файлын зөвхөн хагас нь upload хийгдсэн. + + + No file was uploaded. + Ямар ч файл upload хийгдсэнгүй. + + + No temporary folder was configured in php.ini. + php.ini дээр түр зуурын хавтсыг тохируулаагүй байна, эсвэл тохируулсан хавтас байхгүй байна. + + + Cannot write temporary file to disk. + Түр зуурын файлыг диск руу бичиж болохгүй байна. + + + A PHP extension caused the upload to fail. + PHP extension нь upload -г амжилтгүй болгоод байна. + + + This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. + Энэ коллекц {{ limit }} ба түүнээс дээш тооны элемент агуулах ёстой.|Энэ коллекц {{ limit }} ба түүнээс дээш тооны элемент агуулах ёстой. + + + This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. + Энэ коллекц {{ limit }} ба түүнээс доош тооны элемент агуулах ёстой.|Энэ коллекц {{ limit }} ба түүнээс доош тооны элемент агуулах ёстой. + + + This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. + Энэ коллекц яг {{ limit }} элемент агуулах ёстой.|Энэ коллекц яг {{ limit }} элемент агуулах ёстой. + + + Invalid card number. + Картын дугаар буруу байна. + + + Unsupported card type or invalid card number. + Дэмжигдээгүй картын төрөл эсвэл картын дугаар буруу байна. + + + This is not a valid International Bank Account Number (IBAN). + Энэ утга үнэн зөв Олон Улсын Банкны Дансны Дугаар (IBAN) биш байна. + + + This value is not a valid ISBN-10. + Энэ утга үнэн зөв ISBN-10 биш байна. + + + This value is not a valid ISBN-13. + Энэ утга үнэн зөв ISBN-13 биш байна. + + + This value is neither a valid ISBN-10 nor a valid ISBN-13. + Энэ утга үнэн зөв ISBN-10 юмуу ISBN-13 биш байна. + + + This value is not a valid ISSN. + Энэ утга үнэн зөв ISSN биш байна. + + + This value is not a valid currency. + Энэ утга үнэн бодит валют биш байна. + + + This value should be equal to {{ compared_value }}. + Энэ утга {{ compared_value }} -тaй тэнцүү байх ёстой. + + + This value should be greater than {{ compared_value }}. + Энэ утга {{ compared_value }} -с их байх ёстой. + + + This value should be greater than or equal to {{ compared_value }}. + Энэ утга {{ compared_value }} -тай тэнцүү юмуу эсвэл их байх ёстой. + + + This value should be identical to {{ compared_value_type }} {{ compared_value }}. + Энэ утга {{ compared_value_type }} {{ compared_value }} -тай яг ижил байх ёстой. + + + This value should be less than {{ compared_value }}. + Энэ утга {{ compared_value }} -с бага байх ёстой. + + + This value should be less than or equal to {{ compared_value }}. + Энэ утга {{ compared_value }} -тай ижил юмуу эсвэл бага байх ёстой. + + + This value should not be equal to {{ compared_value }}. + Энэ утга {{ compared_value }} -тай тэнцүү байх ёсгүй. + + + This value should not be identical to {{ compared_value_type }} {{ compared_value }}. + Энэ утга {{ compared_value_type }} {{ compared_value }} -тай яг ижил байх ёсгүй. + + + The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. + Зургийн харьцаа хэтэрхий том байна ({{ ratio }}). Харьцаа нь хамгийн ихдээ {{ max_ratio }} байна. + + + The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. + Зургийн харьцаа хэтэрхий жижиг байна ({{ ratio }}). Харьцаа нь хамгийн багадаа {{ min_ratio }} байна. + + + The image is square ({{ width }}x{{ height }}px). Square images are not allowed. + Зураг дөрвөлжин хэлбэртэй байна ({{ width }}x{{ height }}px). Дөрвөлжин зургууд оруулах боломжгүй. + + + The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed. + Зураг хэвтээ байрлалтай байна ({{ width }}x{{ height }}px). Хэвтээ байрлалтай зургууд оруулах боломжгүй. + + + The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed. + Зургууд босоо байрлалтай байна ({{ width }}x{{ height }}px). Босоо байрлалтай зургууд оруулах боломжгүй. + + + An empty file is not allowed. + Хоосон файл оруулах боломжгүй. + + + The host could not be resolved. + Хост зөв тохирогдоогүй байна. + + + This value does not match the expected {{ charset }} charset. + Энэ утга тооцоолсон {{ charset }} тэмдэгттэй таарахгүй байна. + + + This is not a valid Business Identifier Code (BIC). + Энэ утга үнэн зөв Business Identifier Code (BIC) биш байна. + + + Error + Алдаа + + + This is not a valid UUID. + Энэ утга үнэн зөв UUID биш байна. + + + This value should be a multiple of {{ compared_value }}. + Энэ утга {{ compared_value }} -н үржвэр байх ёстой. + + + This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. + Энэ Business Identifier Code (BIC) код нь IBAN {{ iban }} -тай холбоогүй байна. + + + This value should be valid JSON. + Энэ утга JSON байх ёстой. + + + This collection should contain only unique elements. + Энэ коллекц зөвхөн давтагдахгүй элементүүд агуулах ёстой. + + + This value should be positive. + Энэ утга эерэг байх ёстой. + + + This value should be either positive or zero. + Энэ утга тэг эсвэл эерэг байх ёстой. + + + This value should be negative. + Энэ утга сөрөг байх ёстой. + + + This value should be either negative or zero. + Энэ утга сөрөг эсвэл тэг байх ёстой. + + + This value is not a valid timezone. + Энэ утга үнэн зөв цагийн бүс биш байна. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + Энэ нууц үгийн мэдээлэл алдагдсан байх магадлалтай учраас дахин ашиглагдах ёсгүй. Өөр нууц үг ашиглана уу. + + + This value should be between {{ min }} and {{ max }}. + Энэ утга {{ min }} -с {{ max }} хооронд байх ёстой. + From f10098e9f11a121080169218c0c4627127b2f857 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 9 Feb 2020 18:57:03 +0100 Subject: [PATCH 30/65] [Security] Fix exception name in doc comments --- .../Security/Core/Exception/AuthenticationExpiredException.php | 2 +- .../Security/Guard/Provider/GuardAuthenticationProvider.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php b/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php index 7bc174f05ce82..b45c948acd353 100644 --- a/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php +++ b/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Exception; /** - * AuthenticationServiceException is thrown when an authenticated token becomes un-authenticated between requests. + * AuthenticationExpiredException is thrown when an authenticated token becomes un-authenticated between requests. * * In practice, this is due to the User changing between requests (e.g. password changes), * causes the token to become un-authenticated. diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php index a78a21d49de0e..26890db367385 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -82,7 +82,7 @@ public function authenticate(TokenInterface $token) return $token; } - // this AccountStatusException causes the user to be logged out + // this AccountExpiredException causes the user to be logged out throw new AuthenticationExpiredException(); } From 707c5bade0dd7220b6d7e03dd7e27d66840edeb0 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 11 Feb 2020 11:52:39 +0100 Subject: [PATCH 31/65] [Console] Don't load same-namespace alternatives on exact match found --- src/Symfony/Component/Console/Application.php | 20 ++++++++++++--- .../Console/Tests/ApplicationTest.php | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 1463967ffae08..280a34d5c5b1f 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -645,7 +645,15 @@ public function find($name) // filter out aliases for commands which are already on the list if (\count($commands) > 1) { $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; - $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) { + + if (isset($commandList[$name])) { + return $this->get($name); + } + + foreach ($commands as $k => $nameOrAlias) { + if ($nameOrAlias === $name) { + return $this->get($nameOrAlias); + } if (!$commandList[$nameOrAlias] instanceof Command) { $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias); } @@ -654,8 +662,14 @@ public function find($name) $aliases[$nameOrAlias] = $commandName; - return $commandName === $nameOrAlias || !\in_array($commandName, $commands); - })); + if ($commandName === $nameOrAlias || !\in_array($commandName, $commands)) { + continue; + } + + unset($commands[$k]); + } + + $commands = array_unique($commands); } $exact = \in_array($name, $commands, true) || isset($aliases[$name]); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 559c42599fbdd..8288cfd3269f4 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1642,6 +1642,31 @@ public function testAllExcludesDisabledLazyCommand() $this->assertArrayNotHasKey('disabled', $application->all()); } + public function testFindAlternativesDoesNotLoadSameNamespaceCommandsOnExactMatch() + { + $application = new Application(); + $application->setAutoExit(false); + + $loaded = []; + + $application->setCommandLoader(new FactoryCommandLoader([ + 'foo:bar' => function () use (&$loaded) { + $loaded['foo:bar'] = true; + + return (new Command('foo:bar'))->setCode(function () {}); + }, + 'foo' => function () use (&$loaded) { + $loaded['foo'] = true; + + return (new Command('foo'))->setCode(function () {}); + }, + ])); + + $application->run(new ArrayInput(['command' => 'foo']), new NullOutput()); + + $this->assertSame(['foo' => true], $loaded); + } + protected function getDispatcher($skipCommand = false) { $dispatcher = new EventDispatcher(); From 1c8fbe1cf9d5898094c3f88e582b37d6d4eaede4 Mon Sep 17 00:00:00 2001 From: Massimiliano Arione Date: Thu, 13 Feb 2020 15:46:26 +0100 Subject: [PATCH 32/65] fix links to releases page (formerly known as "roadmap") --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .../Resources/views/Collector/config.html.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 57c15178547d8..859515b3ca554 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -11,7 +11,7 @@ Replace this notice by a short README for your feature/bugfix. This will help people understand your PR and can be used as a start for the documentation. -Additionally (see https://symfony.com/roadmap): +Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - Never break backward compatibility (see https://symfony.com/bc). - Bug fixes must be submitted against the lowest maintained branch where they apply diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig index 94912c5a71f71..58ec64d07ece9 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig @@ -202,7 +202,7 @@ {{ collector.symfonyeom }} {{ collector.symfonyeol }} - View roadmap + View roadmap From 5825e3c58c1b047606ea4c8526b7d93ded2f9a4e Mon Sep 17 00:00:00 2001 From: Massimiliano Arione Date: Thu, 13 Feb 2020 16:21:59 +0100 Subject: [PATCH 33/65] fix anchor --- .../Resources/views/Collector/config.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig index 58ec64d07ece9..b9d130b13e718 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig @@ -202,7 +202,7 @@ {{ collector.symfonyeom }} {{ collector.symfonyeol }} - View roadmap + View roadmap From e1713862997b29dd91f7203da0db6d4ef38355d6 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 14 Feb 2020 07:56:04 +0100 Subject: [PATCH 34/65] sync validator translation files with master --- .../Validator/Resources/translations/validators.de.xlf | 4 ++++ .../Validator/Resources/translations/validators.en.xlf | 4 ++++ .../Validator/Resources/translations/validators.fr.xlf | 4 ++++ .../Validator/Resources/translations/validators.ru.xlf | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf index 8ee3120482267..0702e8dfcdb1e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf @@ -366,6 +366,10 @@ This value should be between {{ min }} and {{ max }}. Dieser Wert sollte zwischen {{ min }} und {{ max }} sein. + + This value is not a valid hostname. + Dieser Wert ist kein gültiger Hostname. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index 100d552076f2c..635e6736f6941 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -366,6 +366,10 @@ This value should be between {{ min }} and {{ max }}. This value should be between {{ min }} and {{ max }}. + + This value is not a valid hostname. + This value is not a valid hostname. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index dc7e73e3c7581..4a7ab3538c41a 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -366,6 +366,10 @@ This value should be between {{ min }} and {{ max }}. Cette valeur doit être comprise entre {{ min }} et {{ max }}. + + This value is not a valid hostname. + Cette valeur n'est pas un nom d'hôte valide. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf index 361be20f796f8..80911a9902910 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ru.xlf @@ -366,6 +366,10 @@ This value should be between {{ min }} and {{ max }}. Значение должно быть между {{ min }} и {{ max }}. + + This value is not a valid hostname. + Значение не является корректным именем хоста. + From 9e431038b204c6ebe53b2d628c0df52df086bd4a Mon Sep 17 00:00:00 2001 From: Christopher Hertel Date: Wed, 12 Feb 2020 22:21:47 +0100 Subject: [PATCH 35/65] fix unix root dir issue --- src/Symfony/Component/Finder/Finder.php | 4 ++++ .../Finder/Iterator/RecursiveDirectoryIterator.php | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index d2ea17d87a00f..33a76cc976f86 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -744,6 +744,10 @@ private function searchInDirectory($dir) */ private function normalizeDir($dir) { + if ('/' === $dir) { + return $dir; + } + $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR); if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) { diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index ab48a2b8a174d..63764d407d30f 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -74,7 +74,11 @@ public function current() } $subPathname .= $this->getFilename(); - return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname); + if ('/' !== $basePath = $this->rootPath) { + $basePath .= $this->directorySeparator; + } + + return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname); } /** From 3f995ac602d42ef036491e43157239ccb0ec351d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 14 Feb 2020 11:01:23 +0100 Subject: [PATCH 36/65] [HttpKernel] fix registering DebugHandlersListener regardless of the PHP_SAPI --- .../HttpKernel/EventListener/DebugHandlersListener.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php index df9df09c0bc32..957a3cdb0f4c4 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php @@ -65,6 +65,9 @@ public function __construct(callable $exceptionHandler = null, LoggerInterface $ */ public function configure(Event $event = null) { + if ($event instanceof ConsoleEvent && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { + return; + } if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMasterRequest()) { return; } @@ -148,7 +151,7 @@ public static function getSubscribedEvents() { $events = [KernelEvents::REQUEST => ['configure', 2048]]; - if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { + if (\defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { $events[ConsoleEvents::COMMAND] = ['configure', 2048]; } From f9659719198f278943dd5401e8a260dd840f86c2 Mon Sep 17 00:00:00 2001 From: Makdessi Alex Date: Thu, 13 Feb 2020 15:34:42 +0100 Subject: [PATCH 37/65] [VarDumper] fixed DateCaster not displaying additional fields --- .../Component/VarDumper/Caster/DateCaster.php | 6 ++- .../VarDumper/Tests/Caster/DateCasterTest.php | 37 ++++++++++++++++++- .../Tests/Fixtures/DateTimeChild.php | 8 ++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/VarDumper/Tests/Fixtures/DateTimeChild.php diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index f3258b19a6f28..70f229a0d8b7d 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -31,7 +31,11 @@ public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') ; - $a = []; + unset( + $a[Caster::PREFIX_DYNAMIC.'date'], + $a[Caster::PREFIX_DYNAMIC.'timezone'], + $a[Caster::PREFIX_DYNAMIC.'timezone_type'] + ); $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title); $stub->class .= $d->format(' @U'); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index da8b4d0fa5c38..87485448dcc90 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -16,6 +16,7 @@ use Symfony\Component\VarDumper\Caster\DateCaster; use Symfony\Component\VarDumper\Cloner\Stub; use Symfony\Component\VarDumper\Test\VarDumperTestTrait; +use Symfony\Component\VarDumper\Tests\Fixtures\DateTimeChild; /** * @author Dany Maillard @@ -55,7 +56,7 @@ public function testCastDateTime($time, $timezone, $xDate, $xTimestamp, $xInfos) $stub = new Stub(); $date = new \DateTime($time, new \DateTimeZone($timezone)); - $cast = DateCaster::castDateTime($date, ['foo' => 'bar'], $stub, false, 0); + $cast = DateCaster::castDateTime($date, Caster::castObject($date, \DateTime::class), $stub, false, 0); $xDump = << "foo" + "\\x00~\\x00date" => $xDate +] +EODUMP; + + $this->assertDumpEquals($xDump, $dateCast); + + $xDump = <<assertDumpMatchesFormat($xDump, $dateCast["\0~\0date"]); + } + /** * @dataProvider provideIntervals */ diff --git a/src/Symfony/Component/VarDumper/Tests/Fixtures/DateTimeChild.php b/src/Symfony/Component/VarDumper/Tests/Fixtures/DateTimeChild.php new file mode 100644 index 0000000000000..2ea2df6514ae0 --- /dev/null +++ b/src/Symfony/Component/VarDumper/Tests/Fixtures/DateTimeChild.php @@ -0,0 +1,8 @@ + Date: Fri, 14 Feb 2020 17:15:50 +0200 Subject: [PATCH 38/65] Set previous exception when rethrown from controller resolver --- .../Component/HttpKernel/Controller/ControllerResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index c981642fee4f0..619628b5c7a98 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())); + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $e->getMessage()), 0, $e); } return $callable; From e13470c823ad8032167aa8cbf905eaaed087ebf9 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 15 Feb 2020 14:27:16 +0100 Subject: [PATCH 39/65] [Console] Inline exact-match handling with 4.4 --- src/Symfony/Component/Console/Application.php | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 280a34d5c5b1f..b5637277e88da 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -608,6 +608,10 @@ public function find($name) } } + if ($this->has($name)) { + return $this->get($name); + } + $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); @@ -645,15 +649,7 @@ public function find($name) // filter out aliases for commands which are already on the list if (\count($commands) > 1) { $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; - - if (isset($commandList[$name])) { - return $this->get($name); - } - - foreach ($commands as $k => $nameOrAlias) { - if ($nameOrAlias === $name) { - return $this->get($nameOrAlias); - } + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) { if (!$commandList[$nameOrAlias] instanceof Command) { $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias); } @@ -662,14 +658,8 @@ public function find($name) $aliases[$nameOrAlias] = $commandName; - if ($commandName === $nameOrAlias || !\in_array($commandName, $commands)) { - continue; - } - - unset($commands[$k]); - } - - $commands = array_unique($commands); + return $commandName === $nameOrAlias || !\in_array($commandName, $commands); + })); } $exact = \in_array($name, $commands, true) || isset($aliases[$name]); From 8c4de564a8697cf63c49c39501060ffb138f4762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Bogusz?= Date: Sun, 16 Feb 2020 16:22:50 +0100 Subject: [PATCH 40/65] [Validator] Add the missing translations for the Polish ("pl") locale --- .../Resources/translations/validators.pl.xlf | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf index f1910c99d5751..d1dd1471a77ca 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf @@ -330,10 +330,46 @@ This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}. Ten kod BIC (Business Identifier Code) nie jest powiązany z międzynarodowym numerem rachunku bankowego (IBAN) {{ iban }}. + + This value should be valid JSON. + Ta wartość powinna być prawidłowym formatem JSON. + + + This collection should contain only unique elements. + Ten zbiór powinien zawierać tylko unikalne elementy. + + + This value should be positive. + Ta wartość powinna być dodatnia. + + + This value should be either positive or zero. + Ta wartość powinna być dodatnia lub równa zero. + + + This value should be negative. + Ta wartość powinna być ujemna. + + + This value should be either negative or zero. + Ta wartość powinna być ujemna lub równa zero. + + + This value is not a valid timezone. + Ta wartość nie jest prawidłową strefą czasową. + + + This password has been leaked in a data breach, it must not be used. Please use another password. + To hasło wyciekło w wyniku naruszenia danych i nie może być użyte. Proszę użyć innego hasła. + This value should be between {{ min }} and {{ max }}. Ta wartość powinna być pomiędzy {{ min }} a {{ max }}. + + This value is not a valid hostname. + Ta wartość nie jest prawidłową nazwą hosta. + From dc11c8d1b8764639ed7d382ff3dfdf6c4011f63a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=A4fer?= Date: Sun, 16 Feb 2020 17:40:22 +0100 Subject: [PATCH 41/65] Docs: Typo, grammar --- .../Component/Security/Core/User/UserInterface.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Security/Core/User/UserInterface.php b/src/Symfony/Component/Security/Core/User/UserInterface.php index 58f6cfb3bb146..fdad6b055b32d 100644 --- a/src/Symfony/Component/Security/Core/User/UserInterface.php +++ b/src/Symfony/Component/Security/Core/User/UserInterface.php @@ -21,10 +21,10 @@ * password (for checking against a submitted password), assigning roles * and so on. * - * Regardless of how your user are loaded or where they come from (a database, - * configuration, web service, etc), you will have a class that implements - * this interface. Objects that implement this interface are created and - * loaded by different objects that implement UserProviderInterface + * Regardless of how your users are loaded or where they come from (a database, + * configuration, web service, etc.), you will have a class that implements + * this interface. Objects that implement this interface are created and + * loaded by different objects that implement UserProviderInterface. * * @see UserProviderInterface * @see AdvancedUserInterface From 2f65a7a2556b09cbee7e7afb64b4bb432eaa5a7e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Feb 2020 12:08:29 +0100 Subject: [PATCH 42/65] [Config] don't throw on missing excluded paths --- .../Component/DependencyInjection/Loader/FileLoader.php | 2 +- .../DependencyInjection/Tests/Loader/FileLoaderTest.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index 77cad3c046d73..0a800f01c3f71 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -110,7 +110,7 @@ private function findClasses($namespace, $pattern, $excludePattern) $excludePrefix = null; if ($excludePattern) { $excludePattern = $parameterBag->unescapeValue($parameterBag->resolveValue($excludePattern)); - foreach ($this->glob($excludePattern, true, $resource) as $path => $info) { + foreach ($this->glob($excludePattern, true, $resource, true) as $path => $info) { if (null === $excludePrefix) { $excludePrefix = $resource->getPrefix(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php index ffe58a67ef3bb..cbcc6995170cd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/FileLoaderTest.php @@ -134,6 +134,13 @@ public function testRegisterClassesWithExclude() ], array_keys($container->getAliases()) ); + + $loader->registerClasses( + new Definition(), + 'Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\\', + 'Prototype/*', + 'Prototype/NotExistingDir' + ); } public function testNestedRegisterClasses() From 63f9e013a1f43b024f2dc73235f41f5076103b3d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Feb 2020 14:07:02 +0100 Subject: [PATCH 43/65] [Ldap] force default network timeout --- src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php index 3ff790d05181f..2dcb215b921a4 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php @@ -107,6 +107,10 @@ protected function configureOptions(OptionsResolver $resolver) $value['referrals'] = $options['referrals']; } + if (!isset($value['network_timeout'])) { + $value['network_timeout'] = ini_get('default_socket_timeout'); + } + return $value; }); From 1c24ccc6352eba5e81d75d2c8dac01d284ef418d Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 18 Feb 2020 22:48:57 +0100 Subject: [PATCH 44/65] fix typo --- .../Security/Guard/Provider/GuardAuthenticationProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php index 26890db367385..ddc8c5029778a 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -82,7 +82,7 @@ public function authenticate(TokenInterface $token) return $token; } - // this AccountExpiredException causes the user to be logged out + // this causes the user to be logged out throw new AuthenticationExpiredException(); } From 094e4bbbc2ba86bb4f2e12aefaf522e0c48ddaf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 19 Feb 2020 15:48:16 +0100 Subject: [PATCH 45/65] Do not rely on the current locale when dumping a Graphviz object Funny bug ! With `de_DE.UTF-8` as locale: ``` php > echo sprintf('%s', 0.5); 0,5 php > echo sprintf('%d', 0.5); 0 php > echo sprintf('%f', 0.5); 0,500000 php > echo (string) 0.5; 0,5 ``` So now we force `'0.5'` --- .../Component/DependencyInjection/Dumper/GraphvizDumper.php | 5 +++-- src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php index f06e6e80d5031..0591e024f5753 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php @@ -32,10 +32,11 @@ class GraphvizDumper extends Dumper { private $nodes; private $edges; + // All values should be strings private $options = [ 'graph' => ['ratio' => 'compress'], - 'node' => ['fontsize' => 11, 'fontname' => 'Arial', 'shape' => 'record'], - 'edge' => ['fontsize' => 9, 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => 0.5], + 'node' => ['fontsize' => '11', 'fontname' => 'Arial', 'shape' => 'record'], + 'edge' => ['fontsize' => '9', 'fontname' => 'Arial', 'color' => 'grey', 'arrowhead' => 'open', 'arrowsize' => '0.5'], 'node.instance' => ['fillcolor' => '#9999ff', 'style' => 'filled'], 'node.definition' => ['fillcolor' => '#eeeeee'], 'node.missing' => ['fillcolor' => '#ff9999', 'style' => 'filled'], diff --git a/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php b/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php index c3d673fa91e58..0f6cb33082936 100644 --- a/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php @@ -26,10 +26,11 @@ */ class GraphvizDumper implements DumperInterface { + // All values should be strings protected static $defaultOptions = [ 'graph' => ['ratio' => 'compress', 'rankdir' => 'LR'], - 'node' => ['fontsize' => 9, 'fontname' => 'Arial', 'color' => '#333333', 'fillcolor' => 'lightblue', 'fixedsize' => true, 'width' => 1], - 'edge' => ['fontsize' => 9, 'fontname' => 'Arial', 'color' => '#333333', 'arrowhead' => 'normal', 'arrowsize' => 0.5], + 'node' => ['fontsize' => '9', 'fontname' => 'Arial', 'color' => '#333333', 'fillcolor' => 'lightblue', 'fixedsize' => '1', 'width' => '1'], + 'edge' => ['fontsize' => '9', 'fontname' => 'Arial', 'color' => '#333333', 'arrowhead' => 'normal', 'arrowsize' => '0.5'], ]; /** From 018ec1ae5cf6609535c61d7b3631a4d20e28702a Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 19 Feb 2020 23:15:06 +0100 Subject: [PATCH 46/65] [DoctrineBridge][DoctrineExtractor] Fix indexBy with custom and some core types --- .../PropertyInfo/DoctrineExtractor.php | 80 ++++++++++++------- .../PropertyInfo/DoctrineExtractorTest.php | 13 +++ .../PropertyInfo/Fixtures/DoctrineDummy.php | 10 +++ .../Fixtures/DoctrineRelation.php | 10 +++ 4 files changed, 85 insertions(+), 28 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index 1902adc0269a4..ea96b59f45043 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -117,7 +117,9 @@ public function getTypes($class, $property, array $context = []) $typeOfField = $subMetadata->getTypeOfField($indexProperty); } - $collectionKeyType = $this->getPhpType($typeOfField); + if (!$collectionKeyType = $this->getPhpType($typeOfField)) { + return null; + } } } @@ -137,39 +139,46 @@ public function getTypes($class, $property, array $context = []) if ($metadata->hasField($property)) { $typeOfField = $metadata->getTypeOfField($property); - $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); - - switch ($typeOfField) { - case DBALType::DATE: - case DBALType::DATETIME: - case DBALType::DATETIMETZ: - case 'vardatetime': - case DBALType::TIME: - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')]; - case 'date_immutable': - case 'datetime_immutable': - case 'datetimetz_immutable': - case 'time_immutable': - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')]; - - case 'dateinterval': - return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')]; - - case DBALType::TARRAY: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; + if (!$builtinType = $this->getPhpType($typeOfField)) { + return null; + } - case DBALType::SIMPLE_ARRAY: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]; + $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); - case DBALType::JSON_ARRAY: - return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; + switch ($builtinType) { + case Type::BUILTIN_TYPE_OBJECT: + switch ($typeOfField) { + case DBALType::DATE: + case DBALType::DATETIME: + case DBALType::DATETIMETZ: + case 'vardatetime': + case DBALType::TIME: + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')]; + + case 'date_immutable': + case 'datetime_immutable': + case 'datetimetz_immutable': + case 'time_immutable': + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')]; + + case 'dateinterval': + return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')]; + } - default: - $builtinType = $this->getPhpType($typeOfField); + break; + case Type::BUILTIN_TYPE_ARRAY: + switch ($typeOfField) { + case DBALType::TARRAY: + case DBALType::JSON_ARRAY: + return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; - return $builtinType ? [new Type($builtinType, $nullable)] : null; + case DBALType::SIMPLE_ARRAY: + return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]; + } } + + return [new Type($builtinType, $nullable)]; } return null; @@ -234,7 +243,22 @@ private function getPhpType($doctrineType) return Type::BUILTIN_TYPE_RESOURCE; case DBALType::OBJECT: + case DBALType::DATE: + case DBALType::DATETIME: + case DBALType::DATETIMETZ: + case 'vardatetime': + case DBALType::TIME: + case 'date_immutable': + case 'datetime_immutable': + case 'datetimetz_immutable': + case 'time_immutable': + case 'dateinterval': return Type::BUILTIN_TYPE_OBJECT; + + case DBALType::TARRAY: + case DBALType::SIMPLE_ARRAY: + case DBALType::JSON_ARRAY: + return Type::BUILTIN_TYPE_ARRAY; } return null; diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index cad2dfeaac89e..9c658a324613c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -11,11 +11,13 @@ namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo; +use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Type as DBALType; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Tools\Setup; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor; +use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation; use Symfony\Component\PropertyInfo\Type; /** @@ -62,6 +64,8 @@ public function testGetProperties() 'bar', 'indexedBar', 'indexedFoo', + 'indexedByDt', + 'indexedByCustomType', ], $this->extractor->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy') ); @@ -153,6 +157,15 @@ public function typesProvider() ['simpleArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]], ['customFoo', null], ['notMapped', null], + ['indexedByDt', [new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + Collection::class, + true, + new Type(Type::BUILTIN_TYPE_OBJECT), + new Type(Type::BUILTIN_TYPE_OBJECT, false, DoctrineRelation::class) + )]], + ['indexedByCustomType', null], ]; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index d02deb15bb7b5..c8bd04e4ec5f4 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -112,4 +112,14 @@ class DoctrineDummy private $bigint; public $notMapped; + + /** + * @OneToMany(targetEntity="DoctrineRelation", mappedBy="dt", indexBy="dt") + */ + protected $indexedByDt; + + /** + * @OneToMany(targetEntity="DoctrineRelation", mappedBy="customType", indexBy="customType") + */ + private $indexedByCustomType; } diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php index 85660d3d6b66c..5730cf81dd493 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineRelation.php @@ -39,4 +39,14 @@ class DoctrineRelation * @ManyToOne(targetEntity="DoctrineDummy", inversedBy="indexedFoo") */ protected $foo; + + /** + * @Column(type="datetime") + */ + private $dt; + + /** + * @Column(type="foo") + */ + private $customType; } From e8f3e8495906389c7d70ebb92c6a04639e5d297e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20TAMARELLE?= Date: Wed, 19 Feb 2020 22:39:02 +0100 Subject: [PATCH 47/65] Use strict assertion in asset tests --- .../Tests/Context/RequestStackContextTest.php | 2 +- .../Component/Asset/Tests/PackageTest.php | 4 ++-- .../Component/Asset/Tests/PackagesTest.php | 16 ++++++++-------- .../Component/Asset/Tests/PathPackageTest.php | 6 +++--- .../Component/Asset/Tests/UrlPackageTest.php | 6 +++--- .../VersionStrategy/EmptyVersionStrategyTest.php | 2 +- .../JsonManifestVersionStrategyTest.php | 6 +++--- .../StaticVersionStrategyTest.php | 4 ++-- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php b/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php index 7f24534eba202..d9a54c066ec3e 100644 --- a/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php +++ b/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php @@ -37,7 +37,7 @@ public function testGetBasePathSet() $requestStackContext = new RequestStackContext($requestStack); - $this->assertEquals($testBasePath, $requestStackContext->getBasePath()); + $this->assertSame($testBasePath, $requestStackContext->getBasePath()); } public function testIsSecureFalse() diff --git a/src/Symfony/Component/Asset/Tests/PackageTest.php b/src/Symfony/Component/Asset/Tests/PackageTest.php index 8f6626ae4d2ad..8d7f7b8a26a71 100644 --- a/src/Symfony/Component/Asset/Tests/PackageTest.php +++ b/src/Symfony/Component/Asset/Tests/PackageTest.php @@ -24,7 +24,7 @@ class PackageTest extends TestCase public function testGetUrl($version, $format, $path, $expected) { $package = new Package($version ? new StaticVersionStrategy($version, $format) : new EmptyVersionStrategy()); - $this->assertEquals($expected, $package->getUrl($path)); + $this->assertSame($expected, $package->getUrl($path)); } public function getConfigs() @@ -50,6 +50,6 @@ public function getConfigs() public function testGetVersion() { $package = new Package(new StaticVersionStrategy('v1')); - $this->assertEquals('v1', $package->getVersion('/foo')); + $this->assertSame('v1', $package->getVersion('/foo')); } } diff --git a/src/Symfony/Component/Asset/Tests/PackagesTest.php b/src/Symfony/Component/Asset/Tests/PackagesTest.php index b2d0de375051e..4b30e30a5e482 100644 --- a/src/Symfony/Component/Asset/Tests/PackagesTest.php +++ b/src/Symfony/Component/Asset/Tests/PackagesTest.php @@ -24,13 +24,13 @@ public function testGetterSetters() $packages->setDefaultPackage($default = $this->getMockBuilder('Symfony\Component\Asset\PackageInterface')->getMock()); $packages->addPackage('a', $a = $this->getMockBuilder('Symfony\Component\Asset\PackageInterface')->getMock()); - $this->assertEquals($default, $packages->getPackage()); - $this->assertEquals($a, $packages->getPackage('a')); + $this->assertSame($default, $packages->getPackage()); + $this->assertSame($a, $packages->getPackage('a')); $packages = new Packages($default, ['a' => $a]); - $this->assertEquals($default, $packages->getPackage()); - $this->assertEquals($a, $packages->getPackage('a')); + $this->assertSame($default, $packages->getPackage()); + $this->assertSame($a, $packages->getPackage('a')); } public function testGetVersion() @@ -40,8 +40,8 @@ public function testGetVersion() ['a' => new Package(new StaticVersionStrategy('a'))] ); - $this->assertEquals('default', $packages->getVersion('/foo')); - $this->assertEquals('a', $packages->getVersion('/foo', 'a')); + $this->assertSame('default', $packages->getVersion('/foo')); + $this->assertSame('a', $packages->getVersion('/foo', 'a')); } public function testGetUrl() @@ -51,8 +51,8 @@ public function testGetUrl() ['a' => new Package(new StaticVersionStrategy('a'))] ); - $this->assertEquals('/foo?default', $packages->getUrl('/foo')); - $this->assertEquals('/foo?a', $packages->getUrl('/foo', 'a')); + $this->assertSame('/foo?default', $packages->getUrl('/foo')); + $this->assertSame('/foo?a', $packages->getUrl('/foo', 'a')); } public function testNoDefaultPackage() diff --git a/src/Symfony/Component/Asset/Tests/PathPackageTest.php b/src/Symfony/Component/Asset/Tests/PathPackageTest.php index d00cc76c2a943..4d57559847eb1 100644 --- a/src/Symfony/Component/Asset/Tests/PathPackageTest.php +++ b/src/Symfony/Component/Asset/Tests/PathPackageTest.php @@ -23,7 +23,7 @@ class PathPackageTest extends TestCase public function testGetUrl($basePath, $format, $path, $expected) { $package = new PathPackage($basePath, new StaticVersionStrategy('v1', $format)); - $this->assertEquals($expected, $package->getUrl($path)); + $this->assertSame($expected, $package->getUrl($path)); } public function getConfigs() @@ -55,7 +55,7 @@ public function testGetUrlWithContext($basePathRequest, $basePath, $format, $pat { $package = new PathPackage($basePath, new StaticVersionStrategy('v1', $format), $this->getContext($basePathRequest)); - $this->assertEquals($expected, $package->getUrl($path)); + $this->assertSame($expected, $package->getUrl($path)); } public function getContextConfigs() @@ -83,7 +83,7 @@ public function testVersionStrategyGivesAbsoluteURL() ->willReturn('https://cdn.com/bar/main.css'); $package = new PathPackage('/subdirectory', $versionStrategy, $this->getContext('/bar')); - $this->assertEquals('https://cdn.com/bar/main.css', $package->getUrl('main.css')); + $this->assertSame('https://cdn.com/bar/main.css', $package->getUrl('main.css')); } private function getContext($basePath) diff --git a/src/Symfony/Component/Asset/Tests/UrlPackageTest.php b/src/Symfony/Component/Asset/Tests/UrlPackageTest.php index 8fc617a682201..196c2ead3b264 100644 --- a/src/Symfony/Component/Asset/Tests/UrlPackageTest.php +++ b/src/Symfony/Component/Asset/Tests/UrlPackageTest.php @@ -24,7 +24,7 @@ class UrlPackageTest extends TestCase public function testGetUrl($baseUrls, $format, $path, $expected) { $package = new UrlPackage($baseUrls, new StaticVersionStrategy('v1', $format)); - $this->assertEquals($expected, $package->getUrl($path)); + $this->assertSame($expected, $package->getUrl($path)); } public function getConfigs() @@ -58,7 +58,7 @@ public function testGetUrlWithContext($secure, $baseUrls, $format, $path, $expec { $package = new UrlPackage($baseUrls, new StaticVersionStrategy('v1', $format), $this->getContext($secure)); - $this->assertEquals($expected, $package->getUrl($path)); + $this->assertSame($expected, $package->getUrl($path)); } public function getContextConfigs() @@ -85,7 +85,7 @@ public function testVersionStrategyGivesAbsoluteURL() ->willReturn('https://cdn.com/bar/main.css'); $package = new UrlPackage('https://example.com', $versionStrategy); - $this->assertEquals('https://cdn.com/bar/main.css', $package->getUrl('main.css')); + $this->assertSame('https://cdn.com/bar/main.css', $package->getUrl('main.css')); } public function testNoBaseUrls() diff --git a/src/Symfony/Component/Asset/Tests/VersionStrategy/EmptyVersionStrategyTest.php b/src/Symfony/Component/Asset/Tests/VersionStrategy/EmptyVersionStrategyTest.php index 430146fd5070b..1728c2e99b4d4 100644 --- a/src/Symfony/Component/Asset/Tests/VersionStrategy/EmptyVersionStrategyTest.php +++ b/src/Symfony/Component/Asset/Tests/VersionStrategy/EmptyVersionStrategyTest.php @@ -29,6 +29,6 @@ public function testApplyVersion() $emptyVersionStrategy = new EmptyVersionStrategy(); $path = 'test-path'; - $this->assertEquals($path, $emptyVersionStrategy->applyVersion($path)); + $this->assertSame($path, $emptyVersionStrategy->applyVersion($path)); } } diff --git a/src/Symfony/Component/Asset/Tests/VersionStrategy/JsonManifestVersionStrategyTest.php b/src/Symfony/Component/Asset/Tests/VersionStrategy/JsonManifestVersionStrategyTest.php index d74f3f6321687..ffcc62b995d37 100644 --- a/src/Symfony/Component/Asset/Tests/VersionStrategy/JsonManifestVersionStrategyTest.php +++ b/src/Symfony/Component/Asset/Tests/VersionStrategy/JsonManifestVersionStrategyTest.php @@ -20,21 +20,21 @@ public function testGetVersion() { $strategy = $this->createStrategy('manifest-valid.json'); - $this->assertEquals('main.123abc.js', $strategy->getVersion('main.js')); + $this->assertSame('main.123abc.js', $strategy->getVersion('main.js')); } public function testApplyVersion() { $strategy = $this->createStrategy('manifest-valid.json'); - $this->assertEquals('css/styles.555def.css', $strategy->getVersion('css/styles.css')); + $this->assertSame('css/styles.555def.css', $strategy->getVersion('css/styles.css')); } public function testApplyVersionWhenKeyDoesNotExistInManifest() { $strategy = $this->createStrategy('manifest-valid.json'); - $this->assertEquals('css/other.css', $strategy->getVersion('css/other.css')); + $this->assertSame('css/other.css', $strategy->getVersion('css/other.css')); } public function testMissingManifestFileThrowsException() diff --git a/src/Symfony/Component/Asset/Tests/VersionStrategy/StaticVersionStrategyTest.php b/src/Symfony/Component/Asset/Tests/VersionStrategy/StaticVersionStrategyTest.php index c56a8726a8459..d054e842f2c55 100644 --- a/src/Symfony/Component/Asset/Tests/VersionStrategy/StaticVersionStrategyTest.php +++ b/src/Symfony/Component/Asset/Tests/VersionStrategy/StaticVersionStrategyTest.php @@ -21,7 +21,7 @@ public function testGetVersion() $version = 'v1'; $path = 'test-path'; $staticVersionStrategy = new StaticVersionStrategy($version); - $this->assertEquals($version, $staticVersionStrategy->getVersion($path)); + $this->assertSame($version, $staticVersionStrategy->getVersion($path)); } /** @@ -31,7 +31,7 @@ public function testApplyVersion($path, $version, $format) { $staticVersionStrategy = new StaticVersionStrategy($version, $format); $formatted = sprintf($format ?: '%s?%s', $path, $version); - $this->assertEquals($formatted, $staticVersionStrategy->applyVersion($path)); + $this->assertSame($formatted, $staticVersionStrategy->applyVersion($path)); } public function getConfigs() From 3515793cb353cb30a260ac76b720288e23a1fefe Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Wed, 19 Feb 2020 20:56:03 +0100 Subject: [PATCH 48/65] fix remember me --- .../Provider/RememberMeAuthenticationProvider.php | 7 +++++++ .../RememberMeAuthenticationProviderTest.php | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php index d9a6883cf9a96..e1a22b79a8b30 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php @@ -15,7 +15,9 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\BadCredentialsException; +use Symfony\Component\Security\Core\Exception\LogicException; use Symfony\Component\Security\Core\User\UserCheckerInterface; +use Symfony\Component\Security\Core\User\UserInterface; class RememberMeAuthenticationProvider implements AuthenticationProviderInterface { @@ -49,6 +51,11 @@ public function authenticate(TokenInterface $token) } $user = $token->getUser(); + + if (!$token->getUser() instanceof UserInterface) { + throw new LogicException(sprintf('Method "%s::getUser()" must return a "%s" instance, "%s" returned.', \get_class($token), UserInterface::class, \is_object($user) ? \get_class($user) : \gettype($user))); + } + $this->userChecker->checkPreAuth($user); $this->userChecker->checkPostAuth($user); diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php index 418cd77df4fc1..ce0502269e012 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/RememberMeAuthenticationProviderTest.php @@ -13,8 +13,10 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Security\Core\Authentication\Provider\RememberMeAuthenticationProvider; +use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken; use Symfony\Component\Security\Core\Exception\DisabledException; use Symfony\Component\Security\Core\Role\Role; +use Symfony\Component\Security\Core\User\User; class RememberMeAuthenticationProviderTest extends TestCase { @@ -24,6 +26,7 @@ public function testSupports() $this->assertTrue($provider->supports($this->getSupportedToken())); $this->assertFalse($provider->supports($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock())); + $this->assertFalse($provider->supports($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\RememberMeToken')->disableOriginalConstructor()->getMock())); } public function testAuthenticateWhenTokenIsNotSupported() @@ -45,6 +48,17 @@ public function testAuthenticateWhenSecretsDoNotMatch() $provider->authenticate($token); } + public function testAuthenticateThrowsOnNonUserInterfaceInstance() + { + $this->expectException('Symfony\Component\Security\Core\Exception\LogicException'); + $this->expectExceptionMessage('Method "Symfony\Component\Security\Core\Authentication\Token\RememberMeToken::getUser()" must return a "Symfony\Component\Security\Core\User\UserInterface" instance, "string" returned.'); + + $provider = $this->getProvider(); + $token = new RememberMeToken(new User('dummyuser', null), 'foo', 'test'); + $token->setUser('stringish-user'); + $provider->authenticate($token); + } + public function testAuthenticateWhenPreChecksFails() { $this->expectException('Symfony\Component\Security\Core\Exception\DisabledException'); From 034e1de6e66a964b3bd4d56bfd78b118b147bcce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcello=20M=C3=B6nkemeyer?= Date: Wed, 19 Feb 2020 14:20:42 +0000 Subject: [PATCH 49/65] [PhpUnitBridge] Use trait instead of extending deprecated class --- .../Bridge/PhpUnit/Legacy/CoverageListenerForV6.php | 7 +++++-- src/Symfony/Bridge/PhpUnit/composer.json | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerForV6.php b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerForV6.php index 0917ea4710c21..1b3ceec161f8a 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerForV6.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerForV6.php @@ -11,8 +11,9 @@ namespace Symfony\Bridge\PhpUnit\Legacy; -use PHPUnit\Framework\BaseTestListener; use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestListenerDefaultImplementation; /** * CoverageListener adds `@covers ` on each test when possible to @@ -22,8 +23,10 @@ * * @internal */ -class CoverageListenerForV6 extends BaseTestListener +class CoverageListenerForV6 implements TestListener { + use TestListenerDefaultImplementation; + private $trait; public function __construct(callable $sutFqcnResolver = null, $warningOnSutNotFound = false) diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json index 25dcb0cd10272..f7d9492613ab6 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" + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0|<6.4,>=6.0" }, "autoload": { "files": [ "bootstrap.php" ], From 0086562c771c2a3e12d901583624e1bbd44aa46e Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 21 Feb 2020 16:29:16 +0100 Subject: [PATCH 50/65] [Validator] Remove specific check for Valid targets --- src/Symfony/Component/Validator/Mapping/ClassMetadata.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index 03b0ae6d8f575..aaa30cddd3b47 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -14,7 +14,6 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\Traverse; -use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\GroupDefinitionException; @@ -183,10 +182,6 @@ public function addConstraint(Constraint $constraint) throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', \get_class($constraint))); } - if ($constraint instanceof Valid) { - throw new ConstraintDefinitionException(sprintf('The constraint "%s" cannot be put on classes.', \get_class($constraint))); - } - if ($constraint instanceof Traverse) { if ($constraint->traverse) { // If traverse is true, traversal should be explicitly enabled From 2993fc9fc52b88e0b95355b1b38f2d07a5d39fa2 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Tue, 18 Feb 2020 23:28:46 +0100 Subject: [PATCH 51/65] Return int if scale = 0 --- .../Core/DataTransformer/NumberToLocalizedStringTransformer.php | 2 +- .../DataTransformer/NumberToLocalizedStringTransformerTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 8eddd85070285..fe9002fe47f5b 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -282,7 +282,7 @@ private function round($number) break; } - $number /= $roundingCoef; + $number = 1 === $roundingCoef ? (int) $number : $number / $roundingCoef; } return $number; diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index 30b93c66feb52..fc76f9b53e398 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -370,7 +370,7 @@ public function testReverseTransformWithRounding($scale, $input, $output, $round { $transformer = new NumberToLocalizedStringTransformer($scale, null, $roundingMode); - $this->assertEquals($output, $transformer->reverseTransform($input)); + $this->assertSame($output, $transformer->reverseTransform($input)); } public function testReverseTransformDoesNotRoundIfNoScale() From 4b83ae7547da7f5cc0b971208ac50dd3889a48dc Mon Sep 17 00:00:00 2001 From: Andrey Sevastianov Date: Thu, 13 Feb 2020 19:48:28 +0200 Subject: [PATCH 52/65] [ExpressionLanguage] Fixed collisions of character operators with object properties --- .../Component/ExpressionLanguage/Lexer.php | 2 +- .../Resources/bin/generate_operator_regex.php | 10 ++++-- .../Tests/ExpressionLanguageTest.php | 11 +++++++ .../ExpressionLanguage/Tests/LexerTest.php | 12 +++++++ .../ExpressionLanguage/Tests/ParserTest.php | 33 +++++++++++++++++++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Lexer.php b/src/Symfony/Component/ExpressionLanguage/Lexer.php index 48b15ffe7c235..01ca293018365 100644 --- a/src/Symfony/Component/ExpressionLanguage/Lexer.php +++ b/src/Symfony/Component/ExpressionLanguage/Lexer.php @@ -73,7 +73,7 @@ public function tokenize($expression) // strings $tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1); $cursor += \strlen($match[0]); - } elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) { + } elseif (preg_match('/(?<=^|[\s(])not in(?=[\s(])|\!\=\=|(?<=^|[\s(])not(?=[\s(])|(?<=^|[\s(])and(?=[\s(])|\=\=\=|\>\=|(?<=^|[\s(])or(?=[\s(])|\<\=|\*\*|\.\.|(?<=^|[\s(])in(?=[\s(])|&&|\|\||(?<=^|[\s(])matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) { // operators $tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1); $cursor += \strlen($match[0]); diff --git a/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php b/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php index e1196c7f514af..c86e962526182 100644 --- a/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php +++ b/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php @@ -15,9 +15,13 @@ $regex = []; foreach ($operators as $operator => $length) { - // an operator that ends with a character must be followed by - // a whitespace or a parenthesis - $regex[] = preg_quote($operator, '/').(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : ''); + // Collisions of character operators: + // - an operator that begins with a character must have a space or a parenthesis before or starting at the beginning of a string + // - an operator that ends with a character must be followed by a whitespace or a parenthesis + $regex[] = + (ctype_alpha($operator[0]) ? '(?<=^|[\s(])' : '') + .preg_quote($operator, '/') + .(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : ''); } echo '/'.implode('|', $regex).'/A'; diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index f69ee57982e8a..fc2f80e17b3aa 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -233,6 +233,17 @@ public function testCachingWithDifferentNamesOrder() $expressionLanguage->compile($expression, ['B' => 'b', 'a']); } + public function testOperatorCollisions() + { + $expressionLanguage = new ExpressionLanguage(); + $expression = 'foo.not in [bar]'; + $compiled = $expressionLanguage->compile($expression, ['foo', 'bar']); + $this->assertSame('in_array($foo->not, [0 => $bar])', $compiled); + + $result = $expressionLanguage->evaluate($expression, ['foo' => (object) ['not' => 'test'], 'bar' => 'test']); + $this->assertTrue($result); + } + /** * @dataProvider getRegisterCallbacks */ diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php index 9ab6b1e843ce0..6c3d1a7d25196 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/LexerTest.php @@ -112,6 +112,18 @@ public function getTokenizeData() [new Token('string', '#foo', 1)], '"#foo"', ], + [ + [ + new Token('name', 'foo', 1), + new Token('punctuation', '.', 4), + new Token('name', 'not', 5), + new Token('operator', 'in', 9), + new Token('punctuation', '[', 12), + new Token('name', 'bar', 13), + new Token('punctuation', ']', 16), + ], + 'foo.not in [bar]', + ], ]; } } diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php index 84b30dc151cf4..2d5a0a6c8c817 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php @@ -53,6 +53,9 @@ public function getParseData() $arguments->addElement(new Node\ConstantNode(2)); $arguments->addElement(new Node\ConstantNode(true)); + $arrayNode = new Node\ArrayNode(); + $arrayNode->addElement(new Node\NameNode('bar')); + return [ [ new Node\NameNode('a'), @@ -151,6 +154,36 @@ public function getParseData() 'bar', ['foo' => 'bar'], ], + + // Operators collisions + [ + new Node\BinaryNode( + 'in', + new Node\GetAttrNode( + new Node\NameNode('foo'), + new Node\ConstantNode('not', true), + new Node\ArgumentsNode(), + Node\GetAttrNode::PROPERTY_CALL + ), + $arrayNode + ), + 'foo.not in [bar]', + ['foo', 'bar'], + ], + [ + new Node\BinaryNode( + 'or', + new Node\UnaryNode('not', new Node\NameNode('foo')), + new Node\GetAttrNode( + new Node\NameNode('foo'), + new Node\ConstantNode('not', true), + new Node\ArgumentsNode(), + Node\GetAttrNode::PROPERTY_CALL + ) + ), + 'not foo or foo.not', + ['foo'], + ], ]; } From 3e35fa59ea443616b79eaa3e0e99e924c969db61 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 21 Feb 2020 17:23:44 +0100 Subject: [PATCH 53/65] [DoctrineBridge] Use new Types::* constants and support new json type --- .../Doctrine/Form/DoctrineOrmTypeGuesser.php | 39 ++++++----- .../PropertyInfo/DoctrineExtractor.php | 59 +++++++++------- .../RememberMe/DoctrineTokenProvider.php | 13 +++- .../PropertyInfo/DoctrineExtractorTest.php | 69 ++++++++++++------- .../PropertyInfo/Fixtures/DoctrineDummy.php | 2 +- .../Fixtures/DoctrineDummy210.php | 30 ++++++++ 6 files changed, 142 insertions(+), 70 deletions(-) create mode 100644 src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy210.php diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index ff4b54d24bdcc..4ab64b428c732 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -15,6 +15,7 @@ use Doctrine\Common\Persistence\Mapping\MappingException as LegacyCommonMappingException; use Doctrine\Common\Util\ClassUtils; use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Mapping\MappingException as LegacyMappingException; use Doctrine\Persistence\ManagerRegistry; @@ -30,12 +31,18 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface private $cache = []; + private static $useDeprecatedConstants; + /** * @param ManagerRegistry|LegacyManagerRegistry $registry */ public function __construct($registry) { $this->registry = $registry; + + if (null === self::$useDeprecatedConstants) { + self::$useDeprecatedConstants = !class_exists(Types::class); + } } /** @@ -57,30 +64,30 @@ public function guessType($class, $property) } switch ($metadata->getTypeOfField($property)) { - case Type::TARRAY: + case self::$useDeprecatedConstants ? Type::TARRAY : 'array': return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', [], Guess::MEDIUM_CONFIDENCE); - case Type::BOOLEAN: + case self::$useDeprecatedConstants ? Type::BOOLEAN : Types::BOOLEAN: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', [], Guess::HIGH_CONFIDENCE); - case Type::DATETIME: - case Type::DATETIMETZ: + case self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE: + case self::$useDeprecatedConstants ? Type::DATETIMETZ : Types::DATETIMETZ_MUTABLE: case 'vardatetime': return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', [], Guess::HIGH_CONFIDENCE); case 'dateinterval': return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateIntervalType', [], Guess::HIGH_CONFIDENCE); - case Type::DATE: + case self::$useDeprecatedConstants ? Type::DATE : Types::DATE_MUTABLE: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', [], Guess::HIGH_CONFIDENCE); - case Type::TIME: + case self::$useDeprecatedConstants ? Type::TIME : Types::TIME_MUTABLE: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TimeType', [], Guess::HIGH_CONFIDENCE); - case Type::DECIMAL: - case Type::FLOAT: + case self::$useDeprecatedConstants ? Type::DECIMAL : Types::DECIMAL: + case self::$useDeprecatedConstants ? Type::FLOAT : Types::FLOAT: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\NumberType', [], Guess::MEDIUM_CONFIDENCE); - case Type::INTEGER: - case Type::BIGINT: - case Type::SMALLINT: + case self::$useDeprecatedConstants ? Type::INTEGER : Types::INTEGER: + case self::$useDeprecatedConstants ? Type::BIGINT : Types::BIGINT: + case self::$useDeprecatedConstants ? Type::SMALLINT : Types::SMALLINT: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\IntegerType', [], Guess::MEDIUM_CONFIDENCE); - case Type::STRING: + case self::$useDeprecatedConstants ? Type::STRING : Types::STRING: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::MEDIUM_CONFIDENCE); - case Type::TEXT: + case self::$useDeprecatedConstants ? Type::TEXT : Types::TEXT: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextareaType', [], Guess::MEDIUM_CONFIDENCE); default: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\TextType', [], Guess::LOW_CONFIDENCE); @@ -103,7 +110,7 @@ public function guessRequired($class, $property) // Check whether the field exists and is nullable or not if (isset($classMetadata->fieldMappings[$property])) { - if (!$classMetadata->isNullable($property) && Type::BOOLEAN !== $classMetadata->getTypeOfField($property)) { + if (!$classMetadata->isNullable($property) && (self::$useDeprecatedConstants ? Type::BOOLEAN : Types::BOOLEAN) !== $classMetadata->getTypeOfField($property)) { return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } @@ -140,7 +147,7 @@ public function guessMaxLength($class, $property) return new ValueGuess($mapping['length'], Guess::HIGH_CONFIDENCE); } - if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) { + if (\in_array($ret[0]->getTypeOfField($property), self::$useDeprecatedConstants ? [Type::DECIMAL, Type::FLOAT] : [Types::DECIMAL, Types::FLOAT])) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } @@ -155,7 +162,7 @@ public function guessPattern($class, $property) { $ret = $this->getMetadata($class); if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { - if (\in_array($ret[0]->getTypeOfField($property), [Type::DECIMAL, Type::FLOAT])) { + if (\in_array($ret[0]->getTypeOfField($property), self::$useDeprecatedConstants ? [Type::DECIMAL, Type::FLOAT] : [Types::DECIMAL, Types::FLOAT])) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } } diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index ea96b59f45043..4ceca2c6acae9 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -14,6 +14,7 @@ use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory as LegacyClassMetadataFactory; use Doctrine\Common\Persistence\Mapping\MappingException as LegacyMappingException; use Doctrine\DBAL\Types\Type as DBALType; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Mapping\MappingException as OrmMappingException; use Doctrine\Persistence\Mapping\ClassMetadataFactory; @@ -31,12 +32,18 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE { private $classMetadataFactory; + private static $useDeprecatedConstants; + /** * @param ClassMetadataFactory|LegacyClassMetadataFactory $classMetadataFactory */ public function __construct($classMetadataFactory) { $this->classMetadataFactory = $classMetadataFactory; + + if (null === self::$useDeprecatedConstants) { + self::$useDeprecatedConstants = !class_exists(Types::class); + } } /** @@ -149,11 +156,11 @@ public function getTypes($class, $property, array $context = []) switch ($builtinType) { case Type::BUILTIN_TYPE_OBJECT: switch ($typeOfField) { - case DBALType::DATE: - case DBALType::DATETIME: - case DBALType::DATETIMETZ: + case self::$useDeprecatedConstants ? DBALType::DATE : Types::DATE_MUTABLE: + case self::$useDeprecatedConstants ? DBALType::DATETIME : Types::DATETIME_MUTABLE: + case self::$useDeprecatedConstants ? DBALType::DATETIMETZ : Types::DATETIMETZ_MUTABLE: case 'vardatetime': - case DBALType::TIME: + case self::$useDeprecatedConstants ? DBALType::TIME : Types::TIME_MUTABLE: return [new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')]; case 'date_immutable': @@ -169,11 +176,12 @@ public function getTypes($class, $property, array $context = []) break; case Type::BUILTIN_TYPE_ARRAY: switch ($typeOfField) { - case DBALType::TARRAY: - case DBALType::JSON_ARRAY: + case self::$useDeprecatedConstants ? DBALType::TARRAY : 'array': + case 'json_array': + case self::$useDeprecatedConstants ? false : Types::JSON: return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)]; - case DBALType::SIMPLE_ARRAY: + case self::$useDeprecatedConstants ? DBALType::SIMPLE_ARRAY : Types::SIMPLE_ARRAY: return [new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING))]; } } @@ -221,33 +229,33 @@ private function isAssociationNullable(array $associationMapping) private function getPhpType($doctrineType) { switch ($doctrineType) { - case DBALType::SMALLINT: - case DBALType::INTEGER: + case self::$useDeprecatedConstants ? DBALType::SMALLINT : Types::SMALLINT: + case self::$useDeprecatedConstants ? DBALType::INTEGER : Types::INTEGER: return Type::BUILTIN_TYPE_INT; - case DBALType::FLOAT: + case self::$useDeprecatedConstants ? DBALType::FLOAT : Types::FLOAT: return Type::BUILTIN_TYPE_FLOAT; - case DBALType::BIGINT: - case DBALType::STRING: - case DBALType::TEXT: - case DBALType::GUID: - case DBALType::DECIMAL: + case self::$useDeprecatedConstants ? DBALType::BIGINT : Types::BIGINT: + case self::$useDeprecatedConstants ? DBALType::STRING : Types::STRING: + case self::$useDeprecatedConstants ? DBALType::TEXT : Types::TEXT: + case self::$useDeprecatedConstants ? DBALType::GUID : Types::GUID: + case self::$useDeprecatedConstants ? DBALType::DECIMAL : Types::DECIMAL: return Type::BUILTIN_TYPE_STRING; - case DBALType::BOOLEAN: + case self::$useDeprecatedConstants ? DBALType::BOOLEAN : Types::BOOLEAN: return Type::BUILTIN_TYPE_BOOL; - case DBALType::BLOB: + case self::$useDeprecatedConstants ? DBALType::BLOB : Types::BLOB: case 'binary': return Type::BUILTIN_TYPE_RESOURCE; - case DBALType::OBJECT: - case DBALType::DATE: - case DBALType::DATETIME: - case DBALType::DATETIMETZ: + case self::$useDeprecatedConstants ? DBALType::OBJECT : Types::OBJECT: + case self::$useDeprecatedConstants ? DBALType::DATE : Types::DATE_MUTABLE: + case self::$useDeprecatedConstants ? DBALType::DATETIME : Types::DATETIME_MUTABLE: + case self::$useDeprecatedConstants ? DBALType::DATETIMETZ : Types::DATETIMETZ_MUTABLE: case 'vardatetime': - case DBALType::TIME: + case self::$useDeprecatedConstants ? DBALType::TIME : Types::TIME_MUTABLE: case 'date_immutable': case 'datetime_immutable': case 'datetimetz_immutable': @@ -255,9 +263,10 @@ private function getPhpType($doctrineType) case 'dateinterval': return Type::BUILTIN_TYPE_OBJECT; - case DBALType::TARRAY: - case DBALType::SIMPLE_ARRAY: - case DBALType::JSON_ARRAY: + case self::$useDeprecatedConstants ? DBALType::TARRAY : 'array': + case self::$useDeprecatedConstants ? DBALType::SIMPLE_ARRAY : Types::SIMPLE_ARRAY: + case 'json_array': + case self::$useDeprecatedConstants ? false : Types::JSON: return Type::BUILTIN_TYPE_ARRAY; } diff --git a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php index 64515fac71840..ef0612df3128f 100644 --- a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php @@ -12,7 +12,8 @@ namespace Symfony\Bridge\Doctrine\Security\RememberMe; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Types\Type as DoctrineType; +use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Types\Types; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken; use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentTokenInterface; use Symfony\Component\Security\Core\Authentication\RememberMe\TokenProviderInterface; @@ -40,9 +41,15 @@ class DoctrineTokenProvider implements TokenProviderInterface { private $conn; + private static $useDeprecatedConstants; + public function __construct(Connection $conn) { $this->conn = $conn; + + if (null === self::$useDeprecatedConstants) { + self::$useDeprecatedConstants = !class_exists(Types::class); + } } /** @@ -90,7 +97,7 @@ public function updateToken($series, $tokenValue, \DateTime $lastUsed) ]; $paramTypes = [ 'value' => \PDO::PARAM_STR, - 'lastUsed' => DoctrineType::DATETIME, + 'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE, 'series' => \PDO::PARAM_STR, ]; $updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes); @@ -119,7 +126,7 @@ public function createNewToken(PersistentTokenInterface $token) 'username' => \PDO::PARAM_STR, 'series' => \PDO::PARAM_STR, 'value' => \PDO::PARAM_STR, - 'lastUsed' => DoctrineType::DATETIME, + 'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE, ]; $this->conn->executeUpdate($sql, $paramValues, $paramTypes); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 9c658a324613c..c4efb6c936106 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -13,10 +13,12 @@ use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Type as DBALType; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Tools\Setup; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor; +use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy210; use Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation; use Symfony\Component\PropertyInfo\Type; @@ -45,29 +47,40 @@ protected function setUp() public function testGetProperties() { + // Fields + $expected = [ + 'id', + 'guid', + 'time', + 'timeImmutable', + 'dateInterval', + 'jsonArray', + 'simpleArray', + 'float', + 'decimal', + 'bool', + 'binary', + 'customFoo', + 'bigint', + ]; + + if (class_exists(Types::class)) { + $expected[] = 'json'; + } + + // Associations + $expected = array_merge($expected, [ + 'foo', + 'bar', + 'indexedBar', + 'indexedFoo', + 'indexedByDt', + 'indexedByCustomType', + ]); + $this->assertEquals( - [ - 'id', - 'guid', - 'time', - 'timeImmutable', - 'dateInterval', - 'json', - 'simpleArray', - 'float', - 'decimal', - 'bool', - 'binary', - 'customFoo', - 'bigint', - 'foo', - 'bar', - 'indexedBar', - 'indexedFoo', - 'indexedByDt', - 'indexedByCustomType', - ], - $this->extractor->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy') + $expected, + $this->extractor->getProperties(!class_exists(Types::class) ? 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy' : DoctrineDummy210::class) ); } @@ -91,7 +104,7 @@ public function testGetPropertiesWithEmbedded() */ public function testExtract($property, array $type = null) { - $this->assertEquals($type, $this->extractor->getTypes('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy', $property, [])); + $this->assertEquals($type, $this->extractor->getTypes(!class_exists(Types::class) ? 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy' : DoctrineDummy210::class, $property, [])); } public function testExtractWithEmbedded() @@ -117,7 +130,7 @@ public function testExtractWithEmbedded() public function typesProvider() { - return [ + $provider = [ ['id', [new Type(Type::BUILTIN_TYPE_INT)]], ['guid', [new Type(Type::BUILTIN_TYPE_STRING)]], ['bigint', [new Type(Type::BUILTIN_TYPE_STRING)]], @@ -128,7 +141,7 @@ public function typesProvider() ['decimal', [new Type(Type::BUILTIN_TYPE_STRING)]], ['bool', [new Type(Type::BUILTIN_TYPE_BOOL)]], ['binary', [new Type(Type::BUILTIN_TYPE_RESOURCE)]], - ['json', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]], + ['jsonArray', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)]], ['foo', [new Type(Type::BUILTIN_TYPE_OBJECT, true, 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineRelation')]], ['bar', [new Type( Type::BUILTIN_TYPE_OBJECT, @@ -167,6 +180,12 @@ public function typesProvider() )]], ['indexedByCustomType', null], ]; + + if (class_exists(Types::class)) { + $provider[] = ['json', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]]; + } + + return $provider; } public function testGetPropertiesCatchException() diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index c8bd04e4ec5f4..81264fad27c5f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -74,7 +74,7 @@ class DoctrineDummy /** * @Column(type="json_array") */ - private $json; + private $jsonArray; /** * @Column(type="simple_array") diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy210.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy210.php new file mode 100644 index 0000000000000..d3916143deab7 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy210.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures; + +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\Id; +use Doctrine\ORM\Mapping\ManyToMany; +use Doctrine\ORM\Mapping\ManyToOne; +use Doctrine\ORM\Mapping\OneToMany; + +/** + * @Entity + */ +final class DoctrineDummy210 extends DoctrineDummy +{ + /** + * @Column(type="json", nullable=true) + */ + private $json; +} From 847d6dc8f367135a10bc783c8890eddf170f4f50 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 24 Feb 2020 15:33:45 +0100 Subject: [PATCH 54/65] prevent method calls on null values --- .../Component/Serializer/Encoder/XmlEncoder.php | 11 ++++++++++- .../Serializer/Normalizer/ArrayDenormalizer.php | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index c1e1109130479..dada438e29d73 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Serializer\Encoder; +use Symfony\Component\Serializer\Exception\BadMethodCallException; use Symfony\Component\Serializer\Exception\NotEncodableValueException; /** @@ -375,7 +376,7 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) { $append = true; - if (\is_array($data) || ($data instanceof \Traversable && !$this->serializer->supportsNormalization($data, $this->format))) { + if (\is_array($data) || ($data instanceof \Traversable && (null === $this->serializer || !$this->serializer->supportsNormalization($data, $this->format)))) { foreach ($data as $key => $data) { //Ah this is the magic @ attribute types. if (0 === strpos($key, '@') && $this->isElementNameValid($attributeName = substr($key, 1))) { @@ -410,6 +411,10 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) } if (\is_object($data)) { + if (null === $this->serializer) { + throw new BadMethodCallException(sprintf('The serializer needs to be set to allow %s() to be used with object data.', __METHOD__)); + } + $data = $this->serializer->normalize($data, $this->format, $this->context); if (null !== $data && !is_scalar($data)) { return $this->buildXml($parentNode, $data, $xmlRootNodeName); @@ -484,6 +489,10 @@ private function selectNodeType(\DOMNode $node, $val) } elseif ($val instanceof \Traversable) { $this->buildXml($node, $val); } elseif (\is_object($val)) { + if (null === $this->serializer) { + throw new BadMethodCallException(sprintf('The serializer needs to be set to allow %s() to be used with object data.', __METHOD__)); + } + return $this->selectNodeType($node, $this->serializer->normalize($val, $this->format, $this->context)); } elseif (is_numeric($val)) { return $this->appendText($node, (string) $val); diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index 93d6fc009b335..702b8bfecdfa6 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -68,6 +68,10 @@ public function denormalize($data, $type, $format = null, array $context = []) */ public function supportsDenormalization($data, $type, $format = null/*, array $context = []*/) { + if (null === $this->serializer) { + throw new BadMethodCallException(sprintf('The serializer needs to be set to allow %s() to be used.', __METHOD__)); + } + $context = \func_num_args() > 3 ? func_get_arg(3) : []; return '[]' === substr($type, -2) From d7250ef620cf2c46c6a27280be7e1b28b289f873 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 24 Feb 2020 18:11:18 +0100 Subject: [PATCH 55/65] [Validator] Add missing translations --- .../Validator/Resources/translations/validators.en.xlf | 4 ++++ .../Validator/Resources/translations/validators.fr.xlf | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index 635e6736f6941..8f8d2d0a0fe98 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -370,6 +370,10 @@ This value is not a valid hostname. This value is not a valid hostname. + + The number of elements in this collection should be a multiple of {{ compared_value }}. + The number of elements in this collection should be a multiple of {{ compared_value }}. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index 4a7ab3538c41a..e54be35c15cca 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -370,6 +370,10 @@ This value is not a valid hostname. Cette valeur n'est pas un nom d'hôte valide. + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Le nombre d'éléments de cette collection doit être un multiple de {{ compared_value }}. + From b515bc9a97f0bb3daf5bb9b6113e3250cd95c094 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 25 Feb 2020 14:09:27 +0100 Subject: [PATCH 56/65] minor #35833 [FrameworkBundle] Add missing items in the unused tag pass whitelist (fabpot) This PR was merged into the 5.1-dev branch. Discussion ---------- [FrameworkBundle] Add missing items in the unused tag pass whitelist | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | n/a | License | MIT | Doc PR | n/a We have some missing tags in the whitelist. I've added a script that adds the missing ones, and added a test to avoid forgetting about updating the whitelist. Commits ------- d1bcc0fc5e [FrameworkBundle] Add a script that checks for missing items in the unused tag whitelist --- .../Compiler/UnusedTagsPass.php | 13 +++- .../bin/check-unused-tags-whitelist.php | 19 ++++++ .../Compiler/UnusedTagsPassTest.php | 23 +++++++ .../Compiler/UnusedTagsPassUtils.php | 68 +++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-tags-whitelist.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassUtils.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php index 606fbd045355e..3cbe534fb99ed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -23,13 +23,17 @@ class UnusedTagsPass implements CompilerPassInterface { private $whitelist = [ 'annotations.cached_reader', + 'auto_alias', + 'cache.pool', 'cache.pool.clearer', + 'config_cache.resource_checker', 'console.command', + 'container.env_var_processor', 'container.hot_path', 'container.service_locator', 'container.service_subscriber', + 'controller.argument_value_resolver', 'controller.service_arguments', - 'config_cache.resource_checker', 'data_collector', 'form.type', 'form.type_extension', @@ -39,7 +43,12 @@ class UnusedTagsPass implements CompilerPassInterface 'kernel.event_listener', 'kernel.event_subscriber', 'kernel.fragment_renderer', + 'kernel.reset', 'monolog.logger', + 'property_info.access_extractor', + 'property_info.list_extractor', + 'property_info.type_extractor', + 'proxy', 'routing.expression_language_provider', 'routing.loader', 'security.expression_language_provider', @@ -53,8 +62,10 @@ class UnusedTagsPass implements CompilerPassInterface 'translation.loader', 'twig.extension', 'twig.loader', + 'twig.runtime', 'validator.constraint_validator', 'validator.initializer', + 'workflow.definition', ]; public function process(ContainerBuilder $container) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-tags-whitelist.php b/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-tags-whitelist.php new file mode 100644 index 0000000000000..7f24973cd8f14 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-tags-whitelist.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +require dirname(__DIR__, 6).'/vendor/autoload.php'; + +use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils; + +$target = dirname(__DIR__, 2).'/DependencyInjection/Compiler/UnusedTagsPass.php'; +$contents = file_get_contents($target); +$contents = preg_replace('{private \$whitelist = \[(.+?)\];}sm', "private \$whitelist = [\n '".implode("',\n '", UnusedTagsPassUtils::getDefinedTags())."',\n ];", $contents); +file_put_contents($target, $contents); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php index 1377a62882494..58011375e74f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php @@ -31,4 +31,27 @@ public function testProcess() $this->assertSame([sprintf('%s: Tag "kenrel.event_subscriber" was defined on service(s) "foo", "bar", but was never used. Did you mean "kernel.event_subscriber"?', UnusedTagsPass::class)], $container->getCompiler()->getLog()); } + + public function testMissingWhitelistTags() + { + if (\dirname((new \ReflectionClass(ContainerBuilder::class))->getFileName(), 3) !== \dirname(__DIR__, 5)) { + $this->markTestSkipped('Tests are not run from the root symfony/symfony metapackage.'); + } + + $this->assertSame(UnusedTagsPassUtils::getDefinedTags(), $this->getWhitelistTags(), 'The src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php file must be updated; run src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-tags-whitelist.php.'); + } + + private function getWhitelistTags() + { + // get tags in UnusedTagsPass + $target = \dirname(__DIR__, 3).'/DependencyInjection/Compiler/UnusedTagsPass.php'; + $contents = file_get_contents($target); + preg_match('{private \$whitelist = \[(.+?)\];}sm', $contents, $matches); + $tags = array_values(array_filter(array_map(function ($str) { + return trim(preg_replace('{^ +\'(.+)\',}', '$1', $str)); + }, explode("\n", $matches[1])))); + sort($tags); + + return $tags; + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassUtils.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassUtils.php new file mode 100644 index 0000000000000..558c3e3c0749d --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassUtils.php @@ -0,0 +1,68 @@ + + * + * 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 Symfony\Component\Finder\Finder; + +class UnusedTagsPassUtils +{ + public static function getDefinedTags() + { + $tags = [ + 'proxy' => true, + ]; + + // get all tags used in XML configs + $files = Finder::create()->files()->name('*.xml')->path('Resources')->notPath('Tests')->in(\dirname(__DIR__, 5)); + foreach ($files as $file) { + $contents = file_get_contents($file); + if (preg_match_all('{files()->name('*.php')->path('DependencyInjection')->notPath('Tests')->in(\dirname(__DIR__, 5)); + foreach ($files as $file) { + $contents = file_get_contents($file); + if (preg_match_all('{findTaggedServiceIds\(\'([^\']+)\'}', $contents, $matches)) { + foreach ($matches[1] as $match) { + if ('my.tag' === $match) { + continue; + } + $tags[$match] = true; + } + } + if (preg_match_all('{findTaggedServiceIds\(\$this->([^,\)]+)}', $contents, $matches)) { + foreach ($matches[1] as $var) { + if (preg_match_all('{\$'.$var.' = \'([^\']+)\'}', $contents, $matches)) { + foreach ($matches[1] as $match) { + $tags[$match] = true; + } + } + } + } + } + + $tags = array_keys($tags); + sort($tags); + + return $tags; + } +} From 159ef1bf1d381bd57391e6079d40b9b479a79b6e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 25 Feb 2020 15:31:47 +0100 Subject: [PATCH 57/65] [FrameworkBundle] Fix test --- .../Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php index 58011375e74f3..a73cdd167133d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php @@ -15,6 +15,9 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +/** + * @requires PHP 7.0 + */ class UnusedTagsPassTest extends TestCase { public function testProcess() From 03530770832552007fde72500b5c96940856307b Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 23 Feb 2020 15:53:58 +0100 Subject: [PATCH 58/65] [Security] Allow switching to another user when already switched --- .../Tests/Functional/SwitchUserTest.php | 6 ++-- .../Bundle/SecurityBundle/composer.json | 2 +- .../Http/Firewall/SwitchUserListener.php | 5 ++-- .../Tests/Firewall/SwitchUserListenerTest.php | 30 +++++++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php index 722bef0f78628..e740ac4666b2b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php @@ -33,15 +33,15 @@ public function testSwitchUser($originalUser, $targetUser, $expectedUser, $expec $this->assertEquals($expectedUser, $client->getProfile()->getCollector('security')->getUser()); } - public function testSwitchedUserCannotSwitchToOther() + public function testSwitchedUserCanSwitchToOther() { $client = $this->createAuthenticatedClient('user_can_switch'); $client->request('GET', '/profile?_switch_user=user_cannot_switch_1'); $client->request('GET', '/profile?_switch_user=user_cannot_switch_2'); - $this->assertEquals(500, $client->getResponse()->getStatusCode()); - $this->assertEquals('user_cannot_switch_1', $client->getProfile()->getCollector('security')->getUser()); + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + $this->assertEquals('user_cannot_switch_2', $client->getProfile()->getCollector('security')->getUser()); } public function testSwitchedUserExit() diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index f0e35c7f3d7e8..84b624ec7b5fe 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -19,7 +19,7 @@ "php": "^5.5.9|>=7.0.8", "ext-xml": "*", "symfony/config": "~3.4|~4.0", - "symfony/security": "~3.4.37|~4.3.10|^4.4.3", + "symfony/security": "~3.4.38|~4.3.10|^4.4.5", "symfony/dependency-injection": "^3.4.3|^4.0.3", "symfony/http-kernel": "~3.4|~4.0", "symfony/polyfill-php70": "~1.0" diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index 70492cc79d84e..a5d077fb310d8 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -134,7 +134,8 @@ private function attemptSwitchUser(Request $request, $username) return $token; } - throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername())); + // User already switched, exit before seamlessly switching to another user + $token = $this->attemptExitUser($request); } if (false === $this->accessDecisionManager->decide($token, [$this->role])) { @@ -152,7 +153,7 @@ private function attemptSwitchUser(Request $request, $username) $this->userChecker->checkPostAuth($user); $roles = $user->getRoles(); - $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->tokenStorage->getToken()); + $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $token); $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index f4060f46b7790..ab77180e53c57 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -191,6 +191,36 @@ public function testSwitchUser() $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $this->tokenStorage->getToken()); } + public function testSwitchUserAlreadySwitched() + { + $originalToken = new UsernamePasswordToken('original', null, 'key', ['ROLE_FOO']); + $alreadySwitchedToken = new UsernamePasswordToken('switched_1', null, 'key', [new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $originalToken)]); + + $tokenStorage = new TokenStorage(); + $tokenStorage->setToken($alreadySwitchedToken); + + $targetUser = new User('kuba', 'password', ['ROLE_FOO', 'ROLE_BAR']); + $this->request->query->set('_switch_user', 'kuba'); + + $this->accessDecisionManager->expects($this->once()) + ->method('decide')->with($originalToken, ['ROLE_ALLOWED_TO_SWITCH']) + ->willReturn(true); + $this->userProvider->expects($this->once()) + ->method('loadUserByUsername') + ->with('kuba') + ->willReturn($targetUser); + $this->userChecker->expects($this->once()) + ->method('checkPostAuth')->with($targetUser); + + $listener = new SwitchUserListener($tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager, null, '_switch_user', 'ROLE_ALLOWED_TO_SWITCH', null, false); + $listener->handle($this->event); + + $this->assertSame([], $this->request->query->all()); + $this->assertSame('', $this->request->server->get('QUERY_STRING')); + $this->assertSame('kuba', $tokenStorage->getToken()->getUsername()); + $this->assertSame($originalToken, $tokenStorage->getToken()->getRoles()[2]->getSource()); + } + public function testSwitchUserWorksWithFalsyUsernames() { $token = new UsernamePasswordToken('username', '', 'key', ['ROLE_FOO']); From f8735cc47b1fd13a98817d7c06ab0dd64a5af788 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Tue, 25 Feb 2020 17:47:03 +0100 Subject: [PATCH 59/65] [DomCrawler][Form] Fix PHPDoc on get & offsetGet --- src/Symfony/Component/DomCrawler/Form.php | 4 +-- .../DomCrawler/FormFieldRegistry.php | 2 +- .../Component/DomCrawler/Tests/FormTest.php | 33 ++++++++++++++++++- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index 375ee531c4a0e..0a86c7e6d4069 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -269,7 +269,7 @@ public function remove($name) * * @param string $name The field name * - * @return FormField The field instance + * @return FormField|FormField[]|FormField[][] The value of the field * * @throws \InvalidArgumentException When field is not present in this form */ @@ -313,7 +313,7 @@ public function offsetExists($name) * * @param string $name The field name * - * @return FormField The associated Field instance + * @return FormField|FormField[]|FormField[][] The value of the field * * @throws \InvalidArgumentException if the field does not exist */ diff --git a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php index 901a5c8dec1cd..3bbcfa74734ef 100644 --- a/src/Symfony/Component/DomCrawler/FormFieldRegistry.php +++ b/src/Symfony/Component/DomCrawler/FormFieldRegistry.php @@ -70,7 +70,7 @@ public function remove($name) * * @param string $name The fully qualified name of the field * - * @return mixed The value of the field + * @return FormField|FormField[]|FormField[][] The value of the field * * @throws \InvalidArgumentException if the field does not exist */ diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 1867f30a651a3..9894eb429a9ee 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DomCrawler\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Component\DomCrawler\Field\TextareaFormField; use Symfony\Component\DomCrawler\Form; use Symfony\Component\DomCrawler\FormFieldRegistry; @@ -953,7 +954,7 @@ protected function createTestMultipleForm() return $dom; } - public function testgetPhpValuesWithEmptyTextarea() + public function testGetPhpValuesWithEmptyTextarea() { $dom = new \DOMDocument(); $dom->loadHTML(' @@ -968,4 +969,34 @@ public function testgetPhpValuesWithEmptyTextarea() $form = new Form($nodes->item(0), 'http://example.com'); $this->assertEquals($form->getPhpValues(), ['example' => '']); } + + public function testGetReturnTypes() + { + $dom = new \DOMDocument(); + $dom->loadHTML(' + +
+ +
+ ' + ); + + $nodes = $dom->getElementsByTagName('form'); + $form = new Form($nodes->item(0), 'http://example.com'); + + // FormField + $this->assertInstanceOf(TextareaFormField::class, $textareaFormField = $form->get('foo[collection][0][bar]')); + + // Array of FormField + $this->assertSame([ + 'bar' => $textareaFormField, + ], $form->get('foo[collection][0]')); + + // Array of array of FormField + $this->assertSame([ + [ + 'bar' => $textareaFormField, + ], + ], $form->get('foo[collection]')); + } } From 491fc5c24d785937c82f5fc8349edbe5155da01f Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Wed, 26 Feb 2020 21:34:36 +0100 Subject: [PATCH 60/65] [Validator][ConstraintValidator] Update wrong PRETTY_DATE doc --- src/Symfony/Component/Validator/ConstraintValidator.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/ConstraintValidator.php b/src/Symfony/Component/Validator/ConstraintValidator.php index 458351fe2ee00..db0ccb60a8cbc 100644 --- a/src/Symfony/Component/Validator/ConstraintValidator.php +++ b/src/Symfony/Component/Validator/ConstraintValidator.php @@ -21,8 +21,8 @@ abstract class ConstraintValidator implements ConstraintValidatorInterface { /** - * Whether to format {@link \DateTime} objects as RFC-3339 dates - * ("Y-m-d H:i:s"). + * Whether to format {@link \DateTime} objects, either with the {@link \IntlDateFormatter} + * (if it is available) or as RFC-3339 dates ("Y-m-d H:i:s"). */ const PRETTY_DATE = 1; @@ -69,7 +69,8 @@ protected function formatTypeOf($value) * in double quotes ("). Objects, arrays and resources are formatted as * "object", "array" and "resource". If the $format bitmask contains * the PRETTY_DATE bit, then {@link \DateTime} objects will be formatted - * as RFC-3339 dates ("Y-m-d H:i:s"). + * with the {@link \IntlDateFormatter}. If it is not available, they will be + * formatted as RFC-3339 dates ("Y-m-d H:i:s"). * * Be careful when passing message parameters to a constraint violation * that (may) contain objects, arrays or resources. These parameters From 9d837ecb345a29386e3bdaee40fcf84ce8ec72ef Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 28 Feb 2020 15:30:03 +0100 Subject: [PATCH 61/65] add German translation --- .../Validator/Resources/translations/validators.de.xlf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf index 0702e8dfcdb1e..a546b86c78a9b 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf @@ -370,6 +370,10 @@ This value is not a valid hostname. Dieser Wert ist kein gültiger Hostname. + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Die Anzahl an Elementen in dieser Sammlung sollte ein Vielfaches von {{ compared_value }} sein. + From c16d1535226aa7e8162e7065adf7f55b242d2744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4dlich?= Date: Sat, 29 Feb 2020 09:54:47 +0100 Subject: [PATCH 62/65] [Validator] Add missing vietnamese translations --- .../Resources/translations/validators.vi.xlf | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf index 95dd7d6665997..ead79d2cd7e5b 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf @@ -362,6 +362,18 @@ This password has been leaked in a data breach, it must not be used. Please use another password. Mật khẩu này đã bị rò rỉ dữ liệu, không được sử dụng nữa. Xin vui lòng sử dụng mật khẩu khác. + + This value should be between {{ min }} and {{ max }}. + Giá trị này nên thuộc giữa {{ min }} và {{ max }}. + + + This value is not a valid hostname. + Giá trị này không phải là tên máy chủ hợp lệ. + + + The number of elements in this collection should be a multiple of {{ compared_value }}. + Số lượng các phần tử trong bộ sưu tập này nên là bội số của {{compared_value}}. + From b389b68c1fcef99de6c31fb5f261d949ff2723dc Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 29 Feb 2020 11:16:22 +0100 Subject: [PATCH 63/65] updated CHANGELOG for 3.4.38 --- CHANGELOG-3.4.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md index f68d58c658948..fc1d9aa398c2d 100644 --- a/CHANGELOG-3.4.md +++ b/CHANGELOG-3.4.md @@ -7,6 +7,36 @@ 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.38 (2020-02-29) + + * bug #35781 [Form] NumberToLocalizedStringTransformer return int if scale = 0 (VincentLanglet) + * bug #35846 [Serializer] prevent method calls on null values (xabbuh) + * bug #35839 [Security] Allow switching to another user when already switched (chalasr) + * bug #35817 [DoctrineBridge] Use new Types::* constants and support new json type (fancyweb) + * bug #35707 [ExpressionLanguage] Fixed collisions of character operators with object properties (Andrej-in-ua) + * bug #35794 [DoctrineBridge][DoctrineExtractor] Fix indexBy with custom and some core types (fancyweb) + * bug #35787 [PhpUnitBridge] Use trait instead of extending deprecated class (marcello-moenkemeyer) + * bug #35792 [Security] Prevent TypeError in case RememberMetoken has no attached user (nikophil) + * bug #35772 [Config] don't throw on missing excluded paths (nicolas-grekas) + * bug #35774 [Ldap] force default network timeout (nicolas-grekas) + * bug #35702 [VarDumper] fixed DateCaster not displaying additional fields (Makdessi Alex) + * bug #35722 [HttpKernel] Set previous exception when rethrown from controller resolver (danut007ro) + * bug #35718 [HttpKernel] fix registering DebugHandlersListener regardless of the PHP_SAPI (nicolas-grekas) + * bug #35693 [Finder] Fix unix root dir issue (chr-hertel) + * bug #35696 [Console] Don't load same-namespace alternatives on exact match (chalasr) + * bug #35605 [HttpFoundation][FrameworkBundle] fix support for samesite in session cookies (fabpot) + * bug #35609 [DoctrineBridge] Fixed submitting ids with query limit or offset (HeahDude) + * bug #34123 [Form] Fix handling of empty_data's \Closure value in Date/Time form types (yceruto) + * bug #35546 [Validator] check for __get method existence if property is uninitialized (alekitto) + * bug #35332 [Yaml][Inline] Fail properly on empty object tag and empty const tag (fancyweb) + * bug #35489 [PhpUnitBridge] Fix running skipped tests expecting only deprecations (chalasr) + * bug #35161 [FrameworkBundle] Check non-null type for numeric type (Arman-Hosseini) + * bug #34059 [DomCrawler] Skip disabled fields processing in Form (sbogx) + * bug #34114 [Console] SymonfyStyle - Check value isset to avoid PHP notice (leevigraham) + * bug #35557 [Config] dont catch instances of Error (nicolas-grekas) + * bug #35532 [Validator] fix access to uninitialized property when getting value (greedyivan) + * bug #35305 [HttpKernel] Fix stale-if-error behavior, add tests (mpdude) + * 3.4.37 (2020-01-21) * bug #35065 [Security] Use supportsClass in addition to UnsupportedUserException (linaori) From 42be173dfefd7fc3ac8fb82f5015f432428d8ba9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 29 Feb 2020 11:16:34 +0100 Subject: [PATCH 64/65] update CONTRIBUTORS for 3.4.38 --- CONTRIBUTORS.md | 178 +++++++++++++++++++++++++++++++----------------- 1 file changed, 114 insertions(+), 64 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index aea14fb7e6c5d..468c90ad49d1d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -17,9 +17,9 @@ Symfony is the result of the work of many people who made the code better - Maxime Steinhausser (ogizanagi) - Ryan Weaver (weaverryan) - Javier Eguiluz (javier.eguiluz) + - Grégoire Pineau (lyrixx) - Jakub Zalas (jakubzalas) - Roland Franssen (ro0) - - Grégoire Pineau (lyrixx) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) - Yonel Ceruto (yonelceruto) @@ -27,31 +27,31 @@ Symfony is the result of the work of many people who made the code better - Abdellatif Ait boudad (aitboudad) - Samuel ROZE (sroze) - Romain Neutron (romain) + - Wouter de Jong (wouterj) - Pascal Borreli (pborreli) - - Wouter De Jong (wouterj) + - Thomas Calvet (fancyweb) - Joseph Bielawski (stloyd) - Alexander M. Turek (derrabus) - Karma Dordrak (drak) - - Thomas Calvet (fancyweb) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) - Hamza Amrouche (simperfit) - - Jeremy Mikola (jmikola) - Jules Pietri (heah) - - Jean-François Simon (jfsimon) + - Jeremy Mikola (jmikola) - Jérémy DERUSSÉ (jderusse) + - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - Eriksen Costa (eriksencosta) - Guilhem Niot (energetick) - - Sarah Khalil (saro0h) - Tobias Nyholm (tobias) + - Sarah Khalil (saro0h) - Jonathan Wage (jwage) - Lynn van der Berg (kjarli) - Diego Saint Esteben (dosten) + - Matthias Pigulla (mpdude) - Alexandre Salomé (alexandresalome) - William Durand (couac) - - Matthias Pigulla (mpdude) - Pierre du Plessis (pierredup) - ornicar - Dany Maillard (maidmaid) @@ -59,29 +59,29 @@ Symfony is the result of the work of many people who made the code better - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - Konstantin Myakshin (koc) + - Grégoire Paris (greg0ire) - Bulat Shakirzyanov (avalanche123) - Valentin Udaltsov (vudaltsov) - - Grégoire Paris (greg0ire) + - Kevin Bond (kbond) - Saša Stamenković (umpirsky) - Peter Rehm (rpet) - - Kevin Bond (kbond) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik + - Gabriel Ostrolucký (gadelat) - Diego Saint Esteben (dii3g0) - Gábor Egyed (1ed) - - Gabriel Ostrolucký (gadelat) - Titouan Galopin (tgalopin) - - Konstantin Kudryashov (everzet) - David Maicher (dmaicher) + - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Mathieu Piot (mpiot) - Vladimir Reznichenko (kalessil) + - Jan Schädlich (jschaedl) - Florin Patan (florinpatan) - Jáchym Toušek (enumag) - Andrej Hudec (pulzarraider) - Michel Weimerskirch (mweimerskirch) - Issei Murasawa (issei_m) - - Jan Schädlich (jschaedl) - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) - Christian Raue @@ -96,20 +96,20 @@ Symfony is the result of the work of many people who made the code better - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) + - Jérôme Tamarelle (gromnan) - Daniel Holmes (dholmes) - Toni Uebernickel (havvg) + - Fran Moreno (franmomu) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - - Jérôme Tamarelle (gromnan) - John Wards (johnwards) - - Fran Moreno (franmomu) - Antoine Hérault (herzult) - Paráda József (paradajozsef) - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER + - Baptiste Clavié (talus) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) - - Baptiste Clavié (talus) - Chris Wilkinson (thewilkybarkid) - Brice BERNARD (brikou) - marc.weistroff @@ -133,10 +133,10 @@ Symfony is the result of the work of many people who made the code better - Tugdual Saunier (tucksaun) - excelwebzone - Gordon Franke (gimler) + - Joel Wurtz (brouznouf) - Fabien Pennequin (fabienpennequin) - Théo FIDRY (theofidry) - Eric GELOEN (gelo) - - Joel Wurtz (brouznouf) - Lars Strojny (lstrojny) - Jannik Zschiesche (apfelbox) - Robert Schönthal (digitalkaoz) @@ -145,6 +145,8 @@ Symfony is the result of the work of many people who made the code better - 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) @@ -155,7 +157,6 @@ Symfony is the result of the work of many people who made the code better - Hidenori Goto (hidenorigoto) - Andréia Bohner (andreia) - Yanick Witschi (toflar) - - Julien Falque (julienfalque) - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) - SpacePossum @@ -163,12 +164,12 @@ Symfony is the result of the work of many people who made the code better - Jérémie Augustin (jaugustin) - François-Xavier de Guillebon (de-gui_f) - Oleg Voronkovich + - Alessandro Chitolina (alekitto) - Philipp Wahala (hifi) - - Massimiliano Arione (garak) - Rafael Dohms (rdohms) - jwdeitch - Mikael Pajunen - - Alessandro Chitolina (alekitto) + - Arman Hosseini (arman) - Niels Keurentjes (curry684) - Vyacheslav Pavlov - Richard van Laak (rvanlaak) @@ -178,9 +179,9 @@ Symfony is the result of the work of many people who made the code better - jeremyFreeAgent (jeremyfreeagent) - Rouven Weßling (realityking) - Jérôme Parmentier (lctrs) + - Andreas Schempp (aschempp) - Clemens Tolboom - Helmer Aaviksoo - - Arman Hosseini (arman) - Hiromi Hishida (77web) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) @@ -193,7 +194,6 @@ Symfony is the result of the work of many people who made the code better - GDIBass - Samuel NELA (snela) - Ben Davies (bendavies) - - Andreas Schempp (aschempp) - James Halsall (jaitsu) - Matthieu Napoli (mnapoli) - Florent Mata (fmata) @@ -226,11 +226,13 @@ Symfony is the result of the work of many people who made the code better - Stadly - Stepan Anchugov (kix) - bronze1man + - Filippo Tessarotto (slamdunk) - sun (sun) - Larry Garfield (crell) - Nikolay Labinskiy (e-moe) - Martin Schuhfuß (usefulthink) - apetitpa + - Antoine Makdessi (amakdessi) - Matthieu Bontemps (mbontemps) - apetitpa - Pierre Minnieur (pminnieur) @@ -246,6 +248,7 @@ Symfony is the result of the work of many people who made the code better - jeff - John Kary (johnkary) - Jan Rosier (rosier) + - Przemysław Bogusz (przemyslaw-bogusz) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - Michele Orselli (orso) @@ -260,9 +263,11 @@ Symfony is the result of the work of many people who made the code better - Tristan Darricau (nicofuma) - Victor Bocharsky (bocharsky_bw) - Tomas Norkūnas (norkunas) + - Wouter J + - Smaine Milianni (ismail1432) - Marcel Beerta (mazen) + - Christopher Hertel (chertel) - Ruud Kamphuis (ruudk) - - Antoine Makdessi (amakdessi) - Maxime Helias (maxhelias) - Pavel Batanov (scaytrase) - Mantis Development @@ -275,7 +280,9 @@ Symfony is the result of the work of many people who made the code better - julien pauli (jpauli) - Lorenz Schori - Sébastien Lavoie (lavoiesl) + - Ahmed TAILOULOUTE (ahmedtai) - Dariusz + - Saif (╯°□°)╯ (azjezz) - Dmitrii Poddubnyi (karser) - Michael Babker (mbabker) - Francois Zaninotto @@ -289,7 +296,6 @@ Symfony is the result of the work of many people who made the code better - Danny Berger (dpb587) - Antonio J. García Lagar (ajgarlag) - Adam Prager (padam87) - - Przemysław Bogusz (przemyslaw-bogusz) - Benoît Burnichon (bburnichon) - Maciej Malarz (malarzm) - Roman Marintšenko (inori) @@ -307,19 +313,17 @@ Symfony is the result of the work of many people who made the code better - Jordan Samouh (jordansamouh) - Baptiste Lafontaine (magnetik) - Jakub Kucharovic (jkucharovic) + - Loick Piera (pyrech) - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - - Filippo Tessarotto - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon - Quynh Xuan Nguyen (xuanquynh) - Jan Sorgalla (jsor) - Ray - - Smaine Milianni (ismail1432) - Chekote - François Pluchino (francoispluchino) - - Christopher Hertel (chertel) - Thomas Adam - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) @@ -327,6 +331,7 @@ Symfony is the result of the work of many people who made the code better - Bob den Otter (bopp) - Thomas Schulz (king2500) - Frank de Jonge (frenkynet) + - Jeroen Spee (jeroens) - Nikita Konstantinov - Wodor Wodorski - Thomas Lallement (raziel057) @@ -339,6 +344,7 @@ Symfony is the result of the work of many people who made the code better - Robert Kiss (kepten) - Zan Baldwin (zanderbaldwin) - Roumen Damianoff (roumen) + - Emanuele Panzeri (thepanz) - Kim Hemsø Rasmussen (kimhemsoe) - Pascal Luna (skalpa) - Wouter Van Hecke @@ -352,7 +358,7 @@ Symfony is the result of the work of many people who made the code better - Christian Schmidt - Patrick Landolt (scube) - MatTheCat - - Loick Piera (pyrech) + - Vilius Grigaliūnas - David Badura (davidbadura) - Chad Sikorra (chadsikorra) - Chris Smith (cs278) @@ -371,8 +377,8 @@ Symfony is the result of the work of many people who made the code better - Andrey Esaulov (andremaha) - Grégoire Passault (gregwar) - Jerzy Zawadzki (jzawadzki) - - Wouter J - Ismael Ambrosi (iambrosi) + - Craig Duncan (duncan3dc) - Emmanuel BORGES (eborges78) - Aurelijus Valeiša (aurelijus) - Jan Decavele (jandc) @@ -386,16 +392,19 @@ Symfony is the result of the work of many people who made the code better - Francesc Rosàs (frosas) - Romain Pierre (romain-pierre) - Julien Galenski (ruian) + - Michael Käfer (michael_kaefer) - Bongiraud Dominique - janschoenherr - Emanuele Gaspari (inmarelibero) - Dariusz Rumiński - Berny Cantos (xphere81) + - Laurent VOULLEMIER (lvo) - Thierry Thuon (lepiaf) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) - Philippe Segatori - Gennady Telegin (gtelegin) + - Mathias Arlaud (mtarld) - Erin Millard - Artur Melo (restless) - Matthew Lewinski (lewinski) @@ -404,6 +413,7 @@ Symfony is the result of the work of many people who made the code better - Nicolas LEFEVRE (nicoweb) - alquerci - Olivier Dolbeau (odolbeau) + - Oleg Andreyev - Mateusz Sip (mateusz_sip) - Francesco Levorato - Vitaliy Zakharov (zakharovvi) @@ -416,22 +426,22 @@ Symfony is the result of the work of many people who made the code better - Artur Eshenbrener - Timo Bakx (timobakx) - Thomas Perez (scullwm) - - Saif Eddin Gmati (azjezz) - Felix Labrecque - Yaroslav Kiliba - Terje Bråten - Robbert Klarenbeek (robbertkl) - Eric Masoero (eric-masoero) + - Denis Brumann (dbrumann) - JhonnyL - hossein zolfi (ocean) - Clément Gautier (clementgautier) - Bastien Jaillot (bastnic) - Dāvis Zālītis (k0d3r1s) - - Emanuele Panzeri (thepanz) - Sanpi - Eduardo Gulias (egulias) - giulio de donato (liuggio) - ShinDarth + - Alan Poulain - Stéphane PY (steph_py) - Philipp Kräutli (pkraeutli) - Grzegorz (Greg) Zdanowski (kiler129) @@ -443,7 +453,6 @@ Symfony is the result of the work of many people who made the code better - Alex Bowers - Philipp Cordes - Costin Bereveanu (schniper) - - Vilius Grigaliūnas - Loïc Chardonnet (gnusat) - Marek Kalnik (marekkalnik) - Vyacheslav Salakhutdinov (megazoll) @@ -488,7 +497,6 @@ Symfony is the result of the work of many people who made the code better - Christophe L. (christophelau) - Sander Toonen (xatoo) - Anthon Pang (robocoder) - - Michael Käfer (michael_kaefer) - Sébastien Santoro (dereckson) - Brian King - Michel Salib (michelsalib) @@ -498,27 +506,28 @@ Symfony is the result of the work of many people who made the code better - Alexandru Furculita (afurculita) - Valentin Jonovs (valentins-jonovs) - Guilhem N (guilhemn) - - Laurent VOULLEMIER (lvo) - Jeanmonod David (jeanmonod) - Christopher Davis (chrisguitarguy) - Webnet team (webnet) - Farhad Safarov - - Jeroen Spee (jeroens) - Jan Schumann - Niklas Fiekas - Markus Bachmann (baachi) - Kévin THERAGE (kevin_therage) + - Erkhembayar Gantulga (erheme318) + - Islam93 - lancergr - Mihai Stancu - Ivan Nikolaev (destillat) - Gildas Quéméner (gquemener) - - Oleg Andreyev - Alessandro Lai (jean85) - Desjardins Jérôme (jewome62) - Arturs Vonda - Josip Kruslin - Matthew Smeets + - Toni Rudolf (toooni) - Asmir Mustafic (goetas) + - Nicolas Philippe (nikophil) - vagrant - Aurimas Niekis (gcds) - EdgarPE @@ -531,6 +540,7 @@ Symfony is the result of the work of many people who made the code better - Chris Sedlmayr (catchamonkey) - Kamil Kokot (pamil) - Seb Koelen + - Antonio Pauletich (x-coder264) - Christoph Mewes (xrstf) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) @@ -542,7 +552,6 @@ Symfony is the result of the work of many people who made the code better - Gonzalo Vilaseca (gonzalovilaseca) - Tarmo Leppänen (tarlepp) - Marcin Sikoń (marphi) - - Denis Brumann (dbrumann) - Dominik Zogg (dominik.zogg) - Marek Pietrzak - Luc Vieillescazes (iamluc) @@ -552,7 +561,6 @@ Symfony is the result of the work of many people who made the code better - Gintautas Miselis - Rob Bast - Roberto Espinoza (respinoza) - - Alan Poulain - Soufian EZ-ZANTAR (soezz) - Zander Baldwin - Gocha Ossinkine (ossinkine) @@ -595,7 +603,6 @@ Symfony is the result of the work of many people who made the code better - Roy Van Ginneken (rvanginneken) - ondrowan - Barry vd. Heuvel (barryvdh) - - Craig Duncan (duncan3dc) - Evan S Kaufman (evanskaufman) - mcben - Jérôme Vieilledent (lolautruche) @@ -606,6 +613,7 @@ Symfony is the result of the work of many people who made the code better - Remi Collet - Vicent Soria Durá (vicentgodella) - Michael Moravec + - Leevi Graham (leevigraham) - Anthony Ferrara - Ioan Negulescu - Jakub Škvára (jskvara) @@ -631,7 +639,9 @@ Symfony is the result of the work of many people who made the code better - Nate (frickenate) - Timothée Barray (tyx) - jhonnyL + - Jacek Jędrzejewski (jacek.jedrzejewski) - sasezaki + - Bozhidar Hristov (warxcell) - Dawid Pakuła (zulusx) - Florian Rey (nervo) - Rodrigo Borrego Bernabé (rodrigobb) @@ -658,13 +668,16 @@ Symfony is the result of the work of many people who made the code better - Jeremy Benoist - fritzmg - Lenar Lõhmus + - Ion Bazan (ionbazan) - Benjamin Laugueux (yzalis) - Zach Badgett (zachbadgett) + - Chi-teck - Aurélien Fredouelle - Pavel Campr (pcampr) - Andrii Dembitskyi - Johnny Robeson (johnny) - Marko Kaznovac (kaznovac) + - Guilliam Xavier - Disquedur - Michiel Boeckaert (milio) - Geoffrey Tran (geoff) @@ -685,6 +698,7 @@ Symfony is the result of the work of many people who made the code better - Dmitry Simushev - Joe Bennett (kralos) - alcaeus + - Thomas Talbot (ioni) - Fred Cox - vitaliytv - Philippe Segatori @@ -703,6 +717,7 @@ Symfony is the result of the work of many people who made the code better - Konstantin S. M. Möllers (ksmmoellers) - James Johnston - Sinan Eldem + - BoShurik - Alexandre Dupuy (satchette) - Malte Blättermann - Simeon Kolev (simeon_kolev9) @@ -725,12 +740,12 @@ Symfony is the result of the work of many people who made the code better - Javier López (loalf) - Reinier Kip - Geoffrey Brier (geoffrey-brier) + - Alexandre Parent - Vladimir Tsykun - Dustin Dobervich (dustin10) - dantleech - Anne-Sophie Bachelard (annesophie) - Sebastian Marek (proofek) - - Erkhembayar Gantulga (erheme318) - zenmate - Michal Trojanowski - David Fuhr @@ -747,7 +762,6 @@ Symfony is the result of the work of many people who made the code better - adev - Stefan Warman - Arkadius Stefanski (arkadius) - - Antonio Pauletich (x-coder264) - Tristan Maindron (tmaindron) - Behnoush Norouzali (behnoush) - Wesley Lancel @@ -759,10 +773,10 @@ 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) - - Islam93 - Shaun Simmons (simshaun) - Richard Bradley - Ulumuddin Yunus (joenoez) @@ -852,7 +866,6 @@ Symfony is the result of the work of many people who made the code better - Yuen-Chi Lian - Tarjei Huse (tarjei) - Besnik Br - - Toni Rudolf (toooni) - Jose Gonzalez - Jonathan (jls-esokia) - Oleksii Zhurbytskyi @@ -871,12 +884,12 @@ Symfony is the result of the work of many people who made the code better - Andrew Tchircoff (andrewtch) - michaelwilliams - 1emming - - Leevi Graham (leevigraham) - Nykopol (nykopol) - Tri Pham (phamuyentri) - Jordan Deitch - Casper Valdemar Poulsen - Josiah (josiah) + - Guillaume Verstraete (versgui) - Greg ORIOL - Joschi Kuphal - John Bohn (jbohn) @@ -890,16 +903,17 @@ Symfony is the result of the work of many people who made the code better - fedor.f - Yosmany Garcia (yosmanyga) - Wouter de Wild + - Trevor North - Degory Valentine - izzyp - Benoit Lévêque (benoit_leveque) - Jeroen Fiege (fieg) - Krzysiek Łabuś - Xavier Lacot (xavier) + - Jon Dufresne - possum - Denis Zunke (donalberto) - Ahmadou Waly Ndiaye (waly) - - Ahmed TAILOULOUTE (ahmedtai) - Jonathan Johnson (jrjohnson) - Olivier Maisonneuve (olineuve) - Pedro Miguel Maymone de Resende (pedroresende) @@ -937,7 +951,6 @@ Symfony is the result of the work of many people who made the code better - Roy Klutman (royklutman) - Sofiane HADDAG (sofhad) - frost-nzcr4 - - Bozhidar Hristov - Laurent Bassin (lbassin) - andrey1s - Abhoryo @@ -954,17 +967,20 @@ Symfony is the result of the work of many people who made the code better - Julie Hourcade (juliehde) - Dmitry Parnas (parnas) - Paul LE CORRE + - Daniel Gorgan - Tony Malzhacker - Mathieu MARCHOIS - Cyril Quintin (cyqui) - Gerard van Helden (drm) - Johnny Peck (johnnypeck) + - Stefan Kruppa - Ivan Menshykov - David Romaní - Patrick Allaert - Gustavo Falco (gfalco) - Matt Robinson (inanimatt) - Kristof Van Cauwenbergh (kristofvc) + - Peter Bowyer (pbowyer) - Aleksey Podskrebyshev - Calin Mihai Pristavu - David Marín Carreño (davefx) @@ -986,8 +1002,6 @@ Symfony is the result of the work of many people who made the code better - Dmytro Boiko (eagle) - Shin Ohno (ganchiku) - Geert De Deckere (geertdd) - - Ion Bazan (ionbazan) - - Jacek Jędrzejewski (jacek.jedrzejewski) - Jan Kramer (jankramer) - abdul malik ikhsan (samsonasik) - Henry Snoek (snoek09) @@ -995,9 +1009,9 @@ Symfony is the result of the work of many people who made the code better - Simone Di Maulo (toretto460) - Christian Morgan - Alexander Miehe (engerim) + - Jesse Rushlow (geeshoe) - Morgan Auchede (mauchede) - Sascha Dens (saschadens) - - Chi-teck - Don Pinkster - Maksim Muruev - Emil Einarsson @@ -1023,7 +1037,6 @@ Symfony is the result of the work of many people who made the code better - Marcos Gómez Vilches (markitosgv) - Matthew Davis (mdavis1982) - Markus S. (staabm) - - Guilliam Xavier - Maks - Antoine LA - den @@ -1046,7 +1059,9 @@ Symfony is the result of the work of many people who made the code better - Koen Kuipers - datibbaw - Erik Saunier (snickers) + - Thiago Cordeiro (thiagocordeiro) - Rootie + - Alireza Mirsepassi (alirezamirsepassi) - Daniel Alejandro Castro Arellano (lexcast) - sensio - Thomas Jarrand @@ -1060,7 +1075,6 @@ Symfony is the result of the work of many people who made the code better - Valérian Galliat - d-ph - Renan Taranto (renan-taranto) - - Thomas Talbot (ioni) - Rikijs Murgs - Uladzimir Tsykun - Ben Ramsey (ramsey) @@ -1077,11 +1091,14 @@ Symfony is the result of the work of many people who made the code better - neghmurken - xaav - Mahmoud Mostafa (mahmoud) - - Mathias Arlaud (mtarld) + - Antonio Jose Cerezo (ajcerezo) + - Baptiste Leduc (korbeil) - Ahmed Abdou - Daniel Iwaniec + - Thomas Ferney - Pieter - Michael Tibben + - Hallison Boaventura (hallisonboaventura) - Billie Thompson - Ganesh Chandrasekaran - Sander Marechal @@ -1093,6 +1110,8 @@ Symfony is the result of the work of many people who made the code better - EStyles (insidestyles) - kevin.nadin - jean pasqualini (darkilliant) + - Iliya Miroslavov Iliev (i.miroslavov) + - Safonov Nikita (ns3777k) - Ross Motley (rossmotley) - ttomor - Mei Gwilym (meigwilym) @@ -1105,6 +1124,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 + - Lorenzo Millucci - Andreas Kleemann - Manuele Menozzi - zairig imad (zairigimad) @@ -1139,11 +1159,14 @@ Symfony is the result of the work of many people who made the code better - Wojciech Sznapka - Luis Pabon (luispabon) - Gavin Staniforth + - Anna Filina (afilina) - Ksaveras Šakys (xawiers) - Ariel J. Birnbaum + - Patrick Luca Fazzi (ap3ir0n) - Danijel Obradović - Pablo Borowicz - Mathieu Santostefano + - Michel Hunziker - Arjan Keeman - Máximo Cuadros (mcuadros) - Lukas Mencl @@ -1175,13 +1198,13 @@ Symfony is the result of the work of many people who made the code better - mlazovla - Alejandro Diaz Torres - Max Beutel + - Jan Vernieuwe (vernija) - Antanas Arvasevicius - Pierre Dudoret - Thomas - Maximilian Berghoff (electricmaxxx) - nacho - Piotr Antosik (antek88) - - Artem Lopata - Vedran Mihočinec (v-m-i) - Sergey Novikov (s12v) - creiner @@ -1199,11 +1222,11 @@ Symfony is the result of the work of many people who made the code better - HypeMC - jfcixmedia - Dominic Tubach - - Nicolas Philippe (nikophil) - Nikita Konstantinov - Martijn Evers - Vitaliy Ryaboy (vitaliy) - Benjamin Paap (benjaminpaap) + - Claus Due (namelesscoder) - Christian - Denis Golubovskiy (bukashk0zzz) - Sergii Smertin (nfx) @@ -1235,6 +1258,7 @@ Symfony is the result of the work of many people who made the code better - Jakub Sacha - Olaf Klischat - orlovv + - Andrey Sevastianov - Claude Dioudonnat - Jonathan Hedstrom - Peter Smeets (darkspartan) @@ -1243,7 +1267,7 @@ Symfony is the result of the work of many people who made the code better - Robert Meijers - James Sansbury - Marcin Chwedziak - - Alexandre Parent + - Benjamin - hjkl - Tony Cosentino (tony-co) - Dan Wilga @@ -1288,14 +1312,17 @@ Symfony is the result of the work of many people who made the code better - Yannick - Vladimir Luchaninov (luchaninov) - spdionis + - maxime.perrimond - rchoquet - gitlost - Taras Girnyk + - Arun Philip - Rémi Leclerc - Jan Vernarsky - Amine Yakoubi - Eduardo García Sanz (coma) - Sergio (deverad) + - Makdessi Alex - James Gilliland - fduch (fduch) - Stuart Fyfe @@ -1315,6 +1342,7 @@ Symfony is the result of the work of many people who made the code better - Roger Webb - Dmitriy Simushev - Pawel Smolinski + - Tomasz (timitao) - Oxan van Leeuwen - pkowalczyk - Soner Sayakci @@ -1329,6 +1357,7 @@ 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 @@ -1363,8 +1392,10 @@ Symfony is the result of the work of many people who made the code better - Mario Young - Ilia (aliance) - Chris McCafferty (cilefen) + - Florian Hermann (fhermann) - Mo Di (modi) - Pablo Schläpfer + - Patrick Berenschot - SuRiKmAn - Gert de Pagter - Jelte Steijaert (jelte) @@ -1384,6 +1415,7 @@ Symfony is the result of the work of many people who made the code better - Justin Reherman (jreherman) - Rubén Calvo (rubencm) - Abdul.Mohsen B. A. A + - Peter Jaap Blaakmeer - Swen van Zanten - Benoît Burnichon - pthompson @@ -1399,6 +1431,7 @@ Symfony is the result of the work of many people who made the code better - Kévin Gomez (kevin) - Mihai Nica (redecs) - Andrei Igna + - Adam Prickett - azine - Dawid Sajdak - Ludek Stepan @@ -1406,6 +1439,7 @@ Symfony is the result of the work of many people who made the code better - Craig Menning (cmenning) - Balázs Benyó (duplabe) - Erika Heidi Reinaldo (erikaheidi) + - Kyryll Maesh (gauss) - Pierre Tachoire (krichprollsch) - Marc J. Schmidt (marcjs) - František Maša @@ -1460,6 +1494,7 @@ 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 @@ -1477,8 +1512,8 @@ Symfony is the result of the work of many people who made the code better - Philip Frank - David Brooks - Lance McNearney - - Guillaume Verstraete - Giorgio Premi + - Aurélien Fontaine - ncou - Ian Carroll - caponica @@ -1488,6 +1523,7 @@ Symfony is the result of the work of many people who made the code better - Pete Mitchell (peterjmit) - Tom Corrigan (tomcorrigan) - Luis Galeas + - Bogdan Scordaliu - Martin Pärtel - Daniel Rotter (danrot) - Frédéric Bouchery (fbouchery) @@ -1497,6 +1533,7 @@ 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 @@ -1527,6 +1564,7 @@ Symfony is the result of the work of many people who made the code better - Arnaud CHASSEUX - tuqqu - Wojciech Gorczyca + - Neagu Cristian-Doru (cristian-neagu) - Rafał Muszyński (rafmus90) - Sébastien Decrême (sebdec) - Timothy Anido (xanido) @@ -1553,6 +1591,7 @@ Symfony is the result of the work of many people who made the code better - Nouhail AL FIDI (alfidi) - Fabian Steiner (fabstei) - Felipy Tavares Amorim (felipyamorim) + - Guillaume Loulier (guikingone) - Klaus Silveira (klaussilveira) - Thomas Chmielowiec (chmielot) - Jānis Lukss @@ -1588,12 +1627,12 @@ Symfony is the result of the work of many people who made the code better - Benhssaein Youssef - Benjamin Bender - Jared Farrish - - Trevor North - karl.rixon - raplider - Konrad Mohrfeldt - Lance Chen - Ciaran McNulty (ciaranmcnulty) + - Dominik Piekarski (dompie) - Andrew (drew) - kor3k kor3k (kor3k) - Stelian Mocanita (stelian) @@ -1607,6 +1646,7 @@ Symfony is the result of the work of many people who made the code better - Hoffmann András - LubenZA - Olivier + - knezmilos13 - Cyril PASCAL - Michael Bessolov - pscheit @@ -1680,6 +1720,7 @@ Symfony is the result of the work of many people who made the code better - Ikhsan Agustian - Arnau González (arnaugm) - Simon Bouland (bouland) + - Dmitry Pigin (dotty) - Jibé Barth (jibbarth) - Matthew Foster (mfoster) - Reyo Stallenberg (reyostallenberg) @@ -1697,7 +1738,6 @@ Symfony is the result of the work of many people who made the code better - stloyd - Andreas - Chris Tickner - - BoShurik - Andrew Coulton - Ulugbek Miniyarov - Jeremy Benoist @@ -1718,7 +1758,6 @@ Symfony is the result of the work of many people who made the code better - Eric Schildkamp - Andreas - Markus - - Daniel Gorgan - kernig - Thomas Chmielowiec - shdev @@ -1762,9 +1801,9 @@ Symfony is the result of the work of many people who made the code better - Andrey Helldar (helldar) - Karim Cassam Chenaï (ka) - Maksym Slesarenko (maksym_slesarenko) + - Marcello Mönkemeyer (marcello-moenkemeyer) - Michal Kurzeja (mkurzeja) - Nicolas Bastien (nicolas_bastien) - - Peter Bowyer (pbowyer) - Nikola Svitlica (thecelavi) - Denis (yethee) - Andrew Zhilin (zhil) @@ -1775,6 +1814,7 @@ Symfony is the result of the work of many people who made the code better - Normunds - Luiz “Felds” Liscia - Thomas Rothe + - Adrien Wilmet - Martin - nietonfir - alefranz @@ -1867,6 +1907,7 @@ Symfony is the result of the work of many people who made the code better - gedrox - Bohan Yang - Alan Bondarchuk + - Pchol - dropfen - Andrey Chernykh - Edvinas Klovas @@ -1889,6 +1930,7 @@ Symfony is the result of the work of many people who made the code better - AmsTaFF (amstaff) - Simon Müller (boscho) - Yannick Bensacq (cibou) + - Cyrille Bourgois (cyrilleb) - Damien (damien_vauchel) - Frédéric G. Marand (fgm) - Freek Van der Herten (freekmurze) @@ -1909,6 +1951,7 @@ Symfony is the result of the work of many people who made the code better - Ahmed Hannachi (tiecoders) - Vincent LEFORT (vlefort) - Walid BOUGHDIRI (walidboughdiri) + - Wim Molenberghs (wimm) - Darryl Hein (xmmedia) - Sadicov Vladimir (xtech) - Kevin EMO (zarcox) @@ -1944,6 +1987,7 @@ Symfony is the result of the work of many people who made the code better - Martin Mayer (martin) - Grzegorz Łukaszewicz (newicz) - Jonny Schmid (schmidjon) + - Ashura - Götz Gottwald - Veres Lajos - Nick Chiu @@ -2015,11 +2059,13 @@ Symfony is the result of the work of many people who made the code better - Achilles Kaloeridis (achilles) - Adria Lopez (adlpz) - Aaron Scherer (aequasi) + - baron (bastien) - Rosio (ben-rosio) - Simon Paarlberg (blamh) - Jeroen Thora (bolle) - Brieuc THOMAS (brieucthomas) - Masao Maeda (brtriver) + - Damien Harper (damien.harper) - Darius Leskauskas (darles) - david perez (davidpv) - Daniël Brekelmans (dbrekelmans) @@ -2059,6 +2105,7 @@ Symfony is the result of the work of many people who made the code better - Pierre Gasté (pierre_g) - Pablo Monterde Perez (plebs) - Jimmy Leger (redpanda) + - Dmitry (staratel) - Marcin Szepczynski (szepczynski) - Cyrille Jouineau (tuxosaurus) - Vladimir Chernyshev (volch) @@ -2069,7 +2116,6 @@ Symfony is the result of the work of many people who made the code better - Angel Fernando Quiroz Campos - Ondrej Mirtes - akimsko - - Stefan Kruppa - Youpie - srsbiz - Taylan Kasap @@ -2087,6 +2133,7 @@ Symfony is the result of the work of many people who made the code better - Damian Sromek - Ben - Evgeniy Tetenchuk + - Sjoerd Adema - Shrey Puranik - Lars Moelleken - dasmfm @@ -2137,6 +2184,7 @@ Symfony is the result of the work of many people who made the code better - BenjaminBeck - Aurelijus Rožėnas - Beno!t POLASZEK + - Armando - Jordan Hoff - znerol - Christian Eikermann @@ -2167,6 +2215,7 @@ Symfony is the result of the work of many people who made the code better - Jack Wright - MrNicodemuz - Anonymous User + - Dieter - Paweł Tomulik - Eric J. Duran - Alexandru Bucur @@ -2224,9 +2273,9 @@ Symfony is the result of the work of many people who made the code better - Shude - Richard Hodgson - Ondřej Führer + - Bogdan - Sema - Elan Ruusamäe - - Jon Dufresne - Thorsten Hallwas - Alex Nostadt - Michael Squires @@ -2278,6 +2327,7 @@ Symfony is the result of the work of many people who made the code better - tirnanog06 - phc - Дмитрий Пацура + - Signor Pedro - ilyes kooli - Ilia Lazarev - Michaël VEROUX @@ -2289,6 +2339,7 @@ Symfony is the result of the work of many people who made the code better - Bilge - ADmad - Nicolas Roudaire + - Matthias Meyer - Temuri Takalandze (abgeo) - Alfonso (afgar) - Andreas Forsblom (aforsblo) @@ -2319,7 +2370,6 @@ Symfony is the result of the work of many people who made the code better - Carsten Eilers (fnc) - Sorin Gitlan (forapathy) - Yohan Giarelli (frequence-web) - - Jesse Rushlow (geeshoe) - Gerry Vandermaesen (gerryvdm) - Ghazy Ben Ahmed (ghazy) - Arash Tabriziyan (ghost098) @@ -2386,10 +2436,10 @@ Symfony is the result of the work of many people who made the code better - Thomas Baumgartner (shoplifter) - Schuyler Jager (sjager) - Volker (skydiablo) + - Success Go (successgo) - Julien Sanchez (sumbobyboys) - Guillermo Gisinger (t3chn0r) - Markus Tacker (tacker) - - Thiago Cordeiro (thiagocordeiro) - Tom Newby (tomnewbyau) - Andrew Clark (tqt_andrew_clark) - David Lumaye (tux1124) @@ -2411,6 +2461,7 @@ Symfony is the result of the work of many people who made the code better - craigmarvelley - Stano Turza - simpson + - Antoine Leblanc - drublic - MaPePeR - Andreas Streichardt @@ -2440,7 +2491,6 @@ Symfony is the result of the work of many people who made the code better - max - Alexander Bauer (abauer) - Ahmad Mayahi (ahmadmayahi) - - Alireza Mirsepassi (alirezamirsepassi) - Mohamed Karnichi (amiral) - Andrew Carter (andrewcarteruk) - Adam Elsodaney (archfizz) From dfc775c59030bb8136e1fefe0da70a7c24489f93 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 29 Feb 2020 11:16:41 +0100 Subject: [PATCH 65/65] updated VERSION for 3.4.38 --- 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 82930d8c27d2b..1c85a2b08fd9b 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.38-DEV'; + const VERSION = '3.4.38'; const VERSION_ID = 30438; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; const RELEASE_VERSION = 38; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy