diff --git a/UPGRADE-4.2.md b/UPGRADE-4.2.md index c1bb03f5aebc..8f7cc54411aa 100644 --- a/UPGRADE-4.2.md +++ b/UPGRADE-4.2.md @@ -192,15 +192,15 @@ HttpKernel * The `Kernel::getRootDir()` and the `kernel.root_dir` parameter have been deprecated * The `KernelInterface::getName()` and the `kernel.name` parameter have been deprecated - * Deprecated the first and second constructor argument of `ConfigDataCollector` - * Deprecated `ConfigDataCollector::getApplicationName()` + * Deprecated the first and second constructor argument of `ConfigDataCollector` + * Deprecated `ConfigDataCollector::getApplicationName()` * Deprecated `ConfigDataCollector::getApplicationVersion()` Messenger --------- * The `MiddlewareInterface::handle()` and `SenderInterface::send()` methods must now return an `Envelope` instance. - * The return value of handlers isn't forwarded anymore by middleware and buses. + * The return value of handlers isn't forwarded anymore by middleware and buses. If you used to return a value, e.g in query bus handlers, you can either: - get the result from the `HandledStamp` in the envelope returned by the bus. - use the `HandleTrait` to leverage a message bus, expecting a single, synchronous message handling and returning its result. @@ -214,15 +214,15 @@ Messenger $query->setResult($yourResult); ``` * The `EnvelopeAwareInterface` was removed and the `MiddlewareInterface::handle()` method now requires an `Envelope` object - as first argument. When using built-in middleware with the provided `MessageBus`, you will not have to do anything. - If you use your own `MessageBusInterface` implementation, you must wrap the message in an `Envelope` before passing it to middleware. + as first argument. When using built-in middleware with the provided `MessageBus`, you will not have to do anything. + If you use your own `MessageBusInterface` implementation, you must wrap the message in an `Envelope` before passing it to middleware. If you created your own middleware, you must change the signature to always expect an `Envelope`. * The `MiddlewareInterface::handle()` second argument (`callable $next`) has changed in favor of a `StackInterface` instance. - When using built-in middleware with the provided `MessageBus`, you will not have to do anything. - If you use your own `MessageBusInterface` implementation, you can use the `StackMiddleware` implementation. + When using built-in middleware with the provided `MessageBus`, you will not have to do anything. + If you use your own `MessageBusInterface` implementation, you can use the `StackMiddleware` implementation. If you created your own middleware, you must change the signature to always expect an `StackInterface` instance and call `$stack->next()->handle($envelope, $stack)` instead of `$next` to call the next middleware: - + Before: ```php public function handle($message, callable $next): Envelope @@ -230,7 +230,7 @@ Messenger // do something before $message = $next($message); // do something after - + return $message; } ``` @@ -242,7 +242,7 @@ Messenger // do something before $envelope = $stack->next()->handle($envelope, $stack); // do something after - + return $envelope; } ``` @@ -251,7 +251,7 @@ Messenger respectively `ReceivedStamp`, `ValidationStamp`, `SerializerStamp` and moved to the `Stamp` namespace. * `AllowNoHandlerMiddleware` has been removed in favor of a new constructor argument on `HandleMessageMiddleware` * The `ConsumeMessagesCommand` class now takes an instance of `Psr\Container\ContainerInterface` - as first constructor argument, i.e a message bus locator. The CLI command now expects a mandatory + as first constructor argument, i.e a message bus locator. The CLI command now expects a mandatory `--bus` option value if there is more than one bus in the locator. * `MessageSubscriberInterface::getHandledMessages()` return value has changed. The value of an array item needs to be an associative array or the method name. diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index 8cc14d0bbe34..c25109048c70 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -100,7 +100,7 @@ $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`)) || ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer`) : `which composer 2> /dev/null`)) - ? $PHP.' '.escapeshellarg($COMPOSER) + ? (file_get_contents($COMPOSER, null, 0, 18) === '#!/usr/bin/env php' ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang : 'composer'; $SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'.($PHPUNIT_VERSION < 6.0 ? ' symfony/yaml': '')); diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index e1a418e84b72..6b18a1dd27c8 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -226,13 +226,11 @@ '%name%': name, '%id%': id, }) %} - {%- elseif label is same as(false) -%} - {% set translation_domain = false %} - {%- else -%} + {%- elseif label is not same as(false) -%} {% set label = name|humanize %} {%- endif -%} {%- endif -%} - + {%- endblock button_widget -%} {%- block submit_widget -%} diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 1ea6ae18b125..1c41992e9b82 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -199,12 +199,12 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - $errorIo->title('Translation Messages Extractor and Dumper'); - $errorIo->comment(sprintf('Generating "%s" translation files for "%s"', $input->getArgument('locale'), $currentName)); + $io->title('Translation Messages Extractor and Dumper'); + $io->comment(sprintf('Generating "%s" translation files for "%s"', $input->getArgument('locale'), $currentName)); // load any messages from templates $extractedCatalogue = new MessageCatalogue($input->getArgument('locale')); - $errorIo->comment('Parsing templates...'); + $io->comment('Parsing templates...'); $this->extractor->setPrefix($input->getOption('prefix')); foreach ($viewsPaths as $path) { if (is_dir($path) || is_file($path)) { @@ -214,7 +214,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // load any existing messages from the translation files $currentCatalogue = new MessageCatalogue($input->getArgument('locale')); - $errorIo->comment('Loading translation files...'); + $io->comment('Loading translation files...'); foreach ($transPaths as $path) { if (is_dir($path)) { $this->reader->read($path, $currentCatalogue); @@ -267,7 +267,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } if ('xlf' === $input->getOption('output-format')) { - $errorIo->comment(sprintf('Xliff output version is %s', $input->getOption('xliff-version'))); + $io->comment(sprintf('Xliff output version is %s', $input->getOption('xliff-version'))); } $resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was'); @@ -279,7 +279,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // save the files if (true === $input->getOption('force')) { - $errorIo->comment('Writing files...'); + $io->comment('Writing files...'); $bundleTransPath = false; foreach ($transPaths as $path) { @@ -299,7 +299,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - $errorIo->success($resultMessage.'.'); + $io->success($resultMessage.'.'); return null; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/ClearRememberMeTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/ClearRememberMeTest.php index 3a1046b0c4a1..51f56c220d33 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/ClearRememberMeTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/ClearRememberMeTest.php @@ -33,7 +33,7 @@ public function testUserChangeClearsCookie() $this->assertNotNull($cookieJar->get('REMEMBERME')); $client->request('GET', '/foo'); - $this->assertSame(200, $client->getResponse()->getStatusCode()); + $this->assertRedirect($client->getResponse(), '/login'); $this->assertNull($cookieJar->get('REMEMBERME')); } } diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index a46df92ba1c1..aa565e6d1528 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -24,7 +24,7 @@ "symfony/security-core": "~4.3", "symfony/security-csrf": "~4.2", "symfony/security-guard": "~4.2", - "symfony/security-http": "~4.3.9|^4.4.1" + "symfony/security-http": "~4.3.10|^4.4.3" }, "require-dev": { "symfony/asset": "~3.4|~4.0", diff --git a/src/Symfony/Component/Debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php index f3fd16e2ac1d..555048dcf4c3 100644 --- a/src/Symfony/Component/Debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php @@ -29,6 +29,10 @@ public static function setUpBeforeClass(): void // get class loaders wrapped by DebugClassLoader if ($function[0] instanceof DebugClassLoader) { $function = $function[0]->getClassLoader(); + + if (!\is_array($function)) { + continue; + } } if ($function[0] instanceof ComposerClassLoader) { diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 14cd5a6858fc..0c104051ba3f 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -277,7 +277,10 @@ private function lexValue() $this->cursor += 1 + $len; } elseif ('"' === $this->data[$this->cursor]) { $value = ''; - ++$this->cursor; + + if (++$this->cursor === $this->end) { + throw $this->createFormatException('Missing quote to end the value'); + } while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) { $value .= $this->data[$this->cursor]; diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index 100bddcaca3f..e86e0ccb54e9 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -40,6 +40,7 @@ public function getEnvDataWithFormatErrors() ['FOO', "Missing = in the environment variable declaration in \".env\" at line 1.\n...FOO...\n ^ line 1 offset 3"], ['FOO="foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO=\"foo...\n ^ line 1 offset 8"], ['FOO=\'foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO='foo...\n ^ line 1 offset 8"], + ["FOO=\"foo\nBAR=\"bar\"", "Missing quote to end the value in \".env\" at line 1.\n...FOO=\"foo\\nBAR=\"bar\"...\n ^ line 1 offset 18"], ['FOO=\'foo'."\n", "Missing quote to end the value in \".env\" at line 1.\n...FOO='foo\\n...\n ^ line 1 offset 9"], ['export FOO', "Unable to unset an environment variable in \".env\" at line 1.\n...export FOO...\n ^ line 1 offset 10"], ['FOO=${FOO', "Unclosed braces on variable expansion in \".env\" at line 1.\n...FOO=\${FOO...\n ^ line 1 offset 9"], diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index cf98bc776694..00caffb02e7a 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -93,6 +93,10 @@ public function getSecret() */ final public function autoLogin(Request $request): ?TokenInterface { + if (($cookie = $request->attributes->get(self::COOKIE_ATTR_NAME)) && null === $cookie->getValue()) { + return null; + } + if (null === $cookie = $request->cookies->get($this->options['name'])) { return null; } diff --git a/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php b/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php index 8dc2042f12c0..cf70ed4cb161 100644 --- a/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php +++ b/src/Symfony/Component/Security/Http/Tests/RememberMe/AbstractRememberMeServicesTest.php @@ -39,6 +39,17 @@ public function testAutoLoginReturnsNullWhenNoCookie() $this->assertNull($service->autoLogin(new Request())); } + public function testAutoLoginReturnsNullAfterLoginFail() + { + $service = $this->getService(null, ['name' => 'foo', 'path' => null, 'domain' => null]); + + $request = new Request(); + $request->cookies->set('foo', 'foo'); + + $service->loginFail($request); + $this->assertNull($service->autoLogin($request)); + } + /** * @group legacy */